Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System / compmod / system / codedom / compiler / CodeValidator.cs
1 //------------------------------------------------------------------------------
2 // <OWNER>Microsoft</OWNER>
3 // 
4 // <copyright file="CodeGenerator.cs" company="Microsoft">
5 //     Copyright (c) Microsoft Corporation.  All rights reserved.
6 // </copyright>                                                                
7 //------------------------------------------------------------------------------
8
9 namespace System.CodeDom.Compiler {
10     using System;
11     using System.CodeDom;
12     using System.Collections;
13     using System.Globalization;
14     using System.IO;
15     
16     // 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
17     // turned into validation code. This code will only validate identifiers and types to check that they are ok in a language
18     // independent manner. By default, this will not be turned on. This gives clients of codedom a mechanism to 
19     // protect themselves against certain types of code injection attacks (using identifier and type names). 
20     // You can pass in any node in the tree that is a subclass of CodeObject.
21     internal class CodeValidator
22     {
23         private static readonly char[] newLineChars = new char[] {'\r', '\n', '\u2028', '\u2029', '\u0085'};
24
25         internal void ValidateIdentifiers(CodeObject e) {
26             if (e is CodeCompileUnit) {
27                 ValidateCodeCompileUnit((CodeCompileUnit)e);
28             } 
29             else if (e is CodeComment) {
30                 ValidateComment((CodeComment)e);
31             } 
32             else if (e is CodeExpression) {
33                 ValidateExpression((CodeExpression)e);
34             }
35             else if (e is CodeNamespace) {
36                 ValidateNamespace((CodeNamespace)e);
37             }
38             else if (e is CodeNamespaceImport) {
39                 ValidateNamespaceImport((CodeNamespaceImport)e);
40             }
41             else if (e is CodeStatement) {
42                 ValidateStatement((CodeStatement)e);
43             }
44             else if (e is CodeTypeMember) {
45                 ValidateTypeMember((CodeTypeMember)e);
46             }
47             else if (e is CodeTypeReference) {
48                 ValidateTypeReference((CodeTypeReference)e);
49             }
50             else if (e is CodeDirective) {
51                 ValidateCodeDirective((CodeDirective) e);
52             }
53             else {
54                 throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
55             }
56         }
57
58         private void ValidateTypeMember(CodeTypeMember e) {
59             ValidateCommentStatements(e.Comments);
60             ValidateCodeDirectives(e.StartDirectives);
61             ValidateCodeDirectives(e.EndDirectives);
62             if (e.LinePragma != null) ValidateLinePragmaStart(e.LinePragma);
63
64             if (e is CodeMemberEvent) {
65                 ValidateEvent((CodeMemberEvent)e);
66             } 
67             else if (e is CodeMemberField) {
68                 ValidateField((CodeMemberField)e);
69             } 
70             else if (e is CodeMemberMethod) {
71                 ValidateMemberMethod((CodeMemberMethod)e);
72             } 
73             else if (e is CodeMemberProperty) {
74                 ValidateProperty((CodeMemberProperty)e);
75             } 
76             else if (e is CodeSnippetTypeMember) {
77                 ValidateSnippetMember((CodeSnippetTypeMember)e);
78             } 
79             else if (e is CodeTypeDeclaration) {
80                 ValidateTypeDeclaration((CodeTypeDeclaration)e);
81             } 
82             else {
83                 throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
84             }
85         }
86
87         private void ValidateCodeCompileUnit(CodeCompileUnit e) {
88             ValidateCodeDirectives(e.StartDirectives);
89             ValidateCodeDirectives(e.EndDirectives);
90             if (e is CodeSnippetCompileUnit) {
91                 ValidateSnippetCompileUnit((CodeSnippetCompileUnit) e);
92             } else {
93                 ValidateCompileUnitStart(e);
94                 ValidateNamespaces(e);
95                 ValidateCompileUnitEnd(e);
96             }
97         }
98
99         private void ValidateSnippetCompileUnit(CodeSnippetCompileUnit e) {
100             if (e.LinePragma != null) ValidateLinePragmaStart(e.LinePragma);
101         }
102
103         private void ValidateCompileUnitStart(CodeCompileUnit e) {
104           if (e.AssemblyCustomAttributes.Count > 0) {
105             ValidateAttributes(e.AssemblyCustomAttributes);
106           }
107         }
108
109         private void ValidateCompileUnitEnd(CodeCompileUnit e) {
110         }
111
112         private void ValidateNamespaces(CodeCompileUnit e) {
113             foreach (CodeNamespace n in e.Namespaces) {
114                 ValidateNamespace(n);
115             }
116         }
117
118         private void ValidateNamespace(CodeNamespace e) {
119             ValidateCommentStatements(e.Comments);
120             ValidateNamespaceStart(e);
121             ValidateNamespaceImports(e);
122             ValidateTypes(e);
123         }
124
125
126         private static void ValidateNamespaceStart(CodeNamespace e) {
127             if (e.Name != null && e.Name.Length > 0) {
128                 ValidateTypeName(e,"Name",e.Name);
129             }
130         }
131
132         private void ValidateNamespaceImports(CodeNamespace e) {
133             IEnumerator en = e.Imports.GetEnumerator();
134             while (en.MoveNext()) {
135                 CodeNamespaceImport imp = (CodeNamespaceImport)en.Current;
136                 if (imp.LinePragma != null) ValidateLinePragmaStart(imp.LinePragma);
137                 ValidateNamespaceImport(imp);
138             }
139         }
140
141         private static void ValidateNamespaceImport(CodeNamespaceImport e) {
142             ValidateTypeName(e,"Namespace",e.Namespace);
143         }
144
145         private void ValidateAttributes(CodeAttributeDeclarationCollection attributes) {
146             if (attributes.Count == 0) return;
147             IEnumerator en = attributes.GetEnumerator();
148             while (en.MoveNext()) {
149                 CodeAttributeDeclaration current = (CodeAttributeDeclaration)en.Current;
150                 ValidateTypeName(current,"Name",current.Name);
151                 ValidateTypeReference(current.AttributeType);
152
153                 foreach (CodeAttributeArgument arg in current.Arguments) {
154                   ValidateAttributeArgument(arg);
155                 }
156             }
157         }
158
159         private void ValidateAttributeArgument(CodeAttributeArgument arg) {
160             if (arg.Name != null && arg.Name.Length > 0) {
161                 ValidateIdentifier(arg,"Name",arg.Name);
162             }
163             ValidateExpression(arg.Value);
164         }
165
166         private void ValidateTypes(CodeNamespace e) {
167             foreach (CodeTypeDeclaration type in e.Types) {
168                 ValidateTypeDeclaration(type);
169             }
170         }
171
172         private void ValidateTypeDeclaration(CodeTypeDeclaration e) { 
173             // This function can be called recursively and will modify the global variable currentClass
174             // 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.
175             CodeTypeDeclaration savedClass = currentClass;
176             currentClass = e;
177
178             ValidateTypeStart(e);
179             ValidateTypeParameters(e.TypeParameters);
180             ValidateTypeMembers(e); // Recursive call can come from here.
181             ValidateTypeReferences(e.BaseTypes);
182
183             currentClass = savedClass;
184         }
185
186         private void ValidateTypeMembers(CodeTypeDeclaration e) {
187             foreach (CodeTypeMember currentMember in e.Members) {
188                         ValidateTypeMember(currentMember);
189                 }
190        }
191
192         private void ValidateTypeParameters(CodeTypeParameterCollection parameters) {
193             for (int i=0; i<parameters.Count; i++) {
194                 ValidateTypeParameter(parameters[i]);
195             }
196         }
197
198         private void ValidateTypeParameter(CodeTypeParameter e) {
199             ValidateIdentifier(e, "Name", e.Name);
200             ValidateTypeReferences(e.Constraints);
201             ValidateAttributes(e.CustomAttributes);
202         }
203
204         private void ValidateField(CodeMemberField e) {
205
206             if (e.CustomAttributes.Count > 0) {
207                 ValidateAttributes(e.CustomAttributes);
208             }
209
210             ValidateIdentifier(e,"Name",e.Name);
211             if (!IsCurrentEnum) {
212                 ValidateTypeReference(e.Type);
213             }   
214
215             if (e.InitExpression != null) {
216                 ValidateExpression(e.InitExpression);
217             }
218         }
219
220         private void ValidateConstructor(CodeConstructor e) {
221             if (e.CustomAttributes.Count > 0) {
222                 ValidateAttributes(e.CustomAttributes);
223             }
224
225             ValidateParameters(e.Parameters);
226
227             CodeExpressionCollection baseArgs = e.BaseConstructorArgs;
228             CodeExpressionCollection thisArgs = e.ChainedConstructorArgs;
229
230             if (baseArgs.Count > 0) {
231                 ValidateExpressionList(baseArgs);
232             }
233
234             if (thisArgs.Count > 0) {
235                 ValidateExpressionList(thisArgs);
236             }
237
238             ValidateStatements(e.Statements);
239         }
240
241         private void ValidateProperty(CodeMemberProperty e) {
242
243             if (e.CustomAttributes.Count > 0) {
244                 ValidateAttributes(e.CustomAttributes);
245             }
246
247             ValidateTypeReference(e.Type);
248             ValidateTypeReferences(e.ImplementationTypes);
249
250             if (e.PrivateImplementationType != null && !IsCurrentInterface) {
251                 ValidateTypeReference(e.PrivateImplementationType);
252             }
253
254             if (e.Parameters.Count > 0 && String.Compare(e.Name, "Item", StringComparison.OrdinalIgnoreCase) == 0) {
255                 ValidateParameters(e.Parameters);
256             }
257             else {
258                 ValidateIdentifier(e,"Name",e.Name);
259             }
260
261             if (e.HasGet) {
262                 if (!(IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract)) {
263                     ValidateStatements(e.GetStatements);
264                 }
265             }
266
267             if (e.HasSet) {
268                 if (!(IsCurrentInterface || (e.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Abstract)) {
269                     ValidateStatements(e.SetStatements);
270                 }
271             }
272         }
273
274         private void ValidateMemberMethod(CodeMemberMethod e) {
275            ValidateCommentStatements(e.Comments);
276            if (e.LinePragma != null) ValidateLinePragmaStart(e.LinePragma);
277
278            ValidateTypeParameters(e.TypeParameters);
279            ValidateTypeReferences(e.ImplementationTypes);
280
281            if (e is CodeEntryPointMethod) {
282                ValidateStatements(((CodeEntryPointMethod)e).Statements);
283            } 
284            else if (e is CodeConstructor) {
285                ValidateConstructor((CodeConstructor)e);
286            }
287            else if (e is CodeTypeConstructor) {
288               ValidateTypeConstructor((CodeTypeConstructor)e);
289            }
290            else  {
291                ValidateMethod(e);
292            }
293         }
294
295         private void ValidateTypeConstructor(CodeTypeConstructor e) {
296             ValidateStatements(e.Statements);
297         }
298
299         private void ValidateMethod(CodeMemberMethod e) {            
300
301             if (e.CustomAttributes.Count > 0) {
302                 ValidateAttributes(e.CustomAttributes);
303             }
304             if (e.ReturnTypeCustomAttributes.Count > 0) {
305                 ValidateAttributes(e.ReturnTypeCustomAttributes);
306             }
307
308             ValidateTypeReference(e.ReturnType);
309             if (e.PrivateImplementationType != null) {
310                 ValidateTypeReference(e.PrivateImplementationType);
311             }
312
313             ValidateIdentifier(e,"Name",e.Name);
314             ValidateParameters(e.Parameters);
315         
316             if (!IsCurrentInterface 
317                 && (e.Attributes & MemberAttributes.ScopeMask) != MemberAttributes.Abstract) {
318                 ValidateStatements(e.Statements);
319             }
320         }
321
322         private void ValidateSnippetMember(CodeSnippetTypeMember e) {
323         }
324
325         private void ValidateTypeStart(CodeTypeDeclaration e) {
326             ValidateCommentStatements(e.Comments);
327             if (e.CustomAttributes.Count > 0) {
328                 ValidateAttributes(e.CustomAttributes);
329             }
330
331             ValidateIdentifier(e,"Name",e.Name);
332             if (IsCurrentDelegate) {
333                 CodeTypeDelegate del = (CodeTypeDelegate)e;
334                 ValidateTypeReference(del.ReturnType);
335                 ValidateParameters(del.Parameters);
336             } else {
337                 foreach (CodeTypeReference typeRef in e.BaseTypes) {
338                     ValidateTypeReference(typeRef);
339                 }
340             }
341         }
342
343         private void ValidateCommentStatements(CodeCommentStatementCollection e) {
344             foreach (CodeCommentStatement comment in e) {
345                  ValidateCommentStatement(comment);
346             }
347         }
348
349         private void ValidateCommentStatement(CodeCommentStatement e) {
350           ValidateComment(e.Comment);
351         }
352
353         private void ValidateComment(CodeComment e) {
354         }
355
356         private void ValidateStatement(CodeStatement e) {
357             ValidateCodeDirectives(e.StartDirectives);
358             ValidateCodeDirectives(e.EndDirectives);
359
360             if (e is CodeCommentStatement) {
361                 ValidateCommentStatement((CodeCommentStatement)e);
362             }
363             else if (e is CodeMethodReturnStatement) {
364                 ValidateMethodReturnStatement((CodeMethodReturnStatement)e);
365             }
366             else if (e is CodeConditionStatement) {
367                 ValidateConditionStatement((CodeConditionStatement)e);
368             }
369             else if (e is CodeTryCatchFinallyStatement) {
370                 ValidateTryCatchFinallyStatement((CodeTryCatchFinallyStatement)e);
371             }
372             else if (e is CodeAssignStatement) {
373                 ValidateAssignStatement((CodeAssignStatement)e);
374             }
375             else if (e is CodeExpressionStatement) {
376                 ValidateExpressionStatement((CodeExpressionStatement)e);
377             }
378             else if (e is CodeIterationStatement) {
379                 ValidateIterationStatement((CodeIterationStatement)e);
380             }
381             else if (e is CodeThrowExceptionStatement) {
382                 ValidateThrowExceptionStatement((CodeThrowExceptionStatement)e);
383             }
384             else if (e is CodeSnippetStatement) {
385                 ValidateSnippetStatement((CodeSnippetStatement)e);
386             }
387             else if (e is CodeVariableDeclarationStatement) {
388                 ValidateVariableDeclarationStatement((CodeVariableDeclarationStatement)e);
389             }
390             else if (e is CodeAttachEventStatement) {
391                 ValidateAttachEventStatement((CodeAttachEventStatement)e);
392             }
393             else if (e is CodeRemoveEventStatement) {
394                 ValidateRemoveEventStatement((CodeRemoveEventStatement)e);
395             }
396             else if (e is CodeGotoStatement) {
397                 ValidateGotoStatement((CodeGotoStatement)e);
398             }
399             else if (e is CodeLabeledStatement) {
400                 ValidateLabeledStatement((CodeLabeledStatement)e);
401             }
402             else {
403                 throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
404             }
405         }
406
407         private void ValidateStatements(CodeStatementCollection stms) {
408             IEnumerator en = stms.GetEnumerator();
409             while (en.MoveNext()) {
410                 ValidateStatement((CodeStatement)en.Current);
411             }
412         }
413
414         private void ValidateExpressionStatement(CodeExpressionStatement e) {
415             ValidateExpression(e.Expression);
416         }
417
418         private void ValidateIterationStatement(CodeIterationStatement e) {
419             ValidateStatement(e.InitStatement);
420             ValidateExpression(e.TestExpression);
421             ValidateStatement(e.IncrementStatement);
422             ValidateStatements(e.Statements);
423         }
424         
425         private void ValidateThrowExceptionStatement(CodeThrowExceptionStatement e) {
426             if (e.ToThrow != null) {
427                 ValidateExpression(e.ToThrow);
428             }
429         }
430
431         private void ValidateMethodReturnStatement(CodeMethodReturnStatement e) {
432             if (e.Expression != null) {
433                 ValidateExpression(e.Expression);
434             }
435         }
436
437         private void ValidateConditionStatement(CodeConditionStatement e) {
438             ValidateExpression(e.Condition);
439             ValidateStatements(e.TrueStatements);
440
441             CodeStatementCollection falseStatemetns = e.FalseStatements;
442             if (falseStatemetns.Count > 0) {
443                 ValidateStatements(e.FalseStatements);
444             }
445         }
446
447         private void ValidateTryCatchFinallyStatement(CodeTryCatchFinallyStatement e) {
448             ValidateStatements(e.TryStatements);
449             CodeCatchClauseCollection catches = e.CatchClauses;
450             if (catches.Count > 0) {
451                 IEnumerator en = catches.GetEnumerator();
452                 while (en.MoveNext()) {
453                     CodeCatchClause current = (CodeCatchClause)en.Current;
454                     ValidateTypeReference(current.CatchExceptionType);
455                     ValidateIdentifier(current,"LocalName",current.LocalName);
456                     ValidateStatements(current.Statements);
457                 }
458             }
459
460             CodeStatementCollection finallyStatements = e.FinallyStatements;
461             if (finallyStatements.Count > 0) {
462                 ValidateStatements(finallyStatements);
463             }
464         }
465
466         private void ValidateAssignStatement(CodeAssignStatement e) {
467             ValidateExpression(e.Left);
468             ValidateExpression(e.Right);
469         }
470
471         private void ValidateAttachEventStatement(CodeAttachEventStatement e) {
472             ValidateEventReferenceExpression(e.Event);
473             ValidateExpression(e.Listener);
474         }
475
476         private void ValidateRemoveEventStatement(CodeRemoveEventStatement e) {
477             ValidateEventReferenceExpression(e.Event);
478             ValidateExpression(e.Listener);
479         }
480
481         private static void ValidateGotoStatement(CodeGotoStatement e) {
482             ValidateIdentifier(e,"Label",e.Label);
483         }
484
485         private void ValidateLabeledStatement(CodeLabeledStatement e) {
486             ValidateIdentifier(e,"Label",e.Label);
487             if (e.Statement != null) {
488                 ValidateStatement(e.Statement);
489             }
490         }
491
492         private void ValidateVariableDeclarationStatement(CodeVariableDeclarationStatement e) {
493             ValidateTypeReference(e.Type);
494             ValidateIdentifier(e,"Name",e.Name);
495             if (e.InitExpression != null) {
496                 ValidateExpression(e.InitExpression);
497             }
498         }
499
500         private void ValidateLinePragmaStart(CodeLinePragma e) {
501         }
502
503         private void ValidateEvent(CodeMemberEvent e) {
504
505             if (e.CustomAttributes.Count > 0) {
506                 ValidateAttributes(e.CustomAttributes);
507             }
508             if (e.PrivateImplementationType != null) {
509                 ValidateTypeReference(e.Type);
510                 ValidateIdentifier(e,"Name",e.Name);
511             }
512
513             ValidateTypeReferences(e.ImplementationTypes);
514         }
515
516         private void ValidateParameters(CodeParameterDeclarationExpressionCollection parameters) {
517             IEnumerator en = parameters.GetEnumerator();
518             while (en.MoveNext()) {
519                 CodeParameterDeclarationExpression current = (CodeParameterDeclarationExpression)en.Current;
520                 ValidateParameterDeclarationExpression(current);
521             }
522         }
523
524         private void ValidateSnippetStatement(CodeSnippetStatement e) {
525         }
526
527         private void ValidateExpressionList(CodeExpressionCollection expressions) {
528             IEnumerator en = expressions.GetEnumerator();
529             while (en.MoveNext()) {
530                 ValidateExpression((CodeExpression)en.Current);
531             }
532         }
533
534         private static void ValidateTypeReference(CodeTypeReference e) {
535             String baseType = e.BaseType;
536             ValidateTypeName(e,"BaseType",baseType);
537             ValidateArity(e);
538             ValidateTypeReferences(e.TypeArguments);
539         }
540
541         private static void ValidateTypeReferences(CodeTypeReferenceCollection refs) {
542             for (int i=0; i<refs.Count; i++) {
543                 ValidateTypeReference(refs[i]);
544             }
545         }
546
547         private static void ValidateArity(CodeTypeReference e) {
548             // Verify that the number of TypeArguments agrees with the arity on the type.  
549             string baseType = e.BaseType;
550             int totalTypeArgs = 0;
551             for (int i=0; i<baseType.Length; i++) {
552                 if (baseType[i] == '`') {
553                     i++;    // skip the '
554                     int numTypeArgs = 0;
555                     while (i < baseType.Length && baseType[i] >= '0' && baseType[i] <='9') {
556                         numTypeArgs = numTypeArgs*10 + (baseType[i] - '0');
557                         i++;
558                     }
559             
560                     totalTypeArgs += numTypeArgs;
561                 }
562             }
563
564             // Check if we have zero type args for open types.
565             if ((totalTypeArgs != e.TypeArguments.Count) && (e.TypeArguments.Count != 0)) {
566                 throw new ArgumentException(SR.GetString(SR.ArityDoesntMatch, baseType, e.TypeArguments.Count));
567             }
568         }
569
570         private static void ValidateTypeName(Object e, String propertyName, String typeName) {
571             if (!CodeGenerator.IsValidLanguageIndependentTypeName(typeName)) {
572                String message = SR.GetString(SR.InvalidTypeName, typeName, propertyName, e.GetType().FullName);
573                throw new ArgumentException(message, "typeName");
574             }
575         }
576
577         private static void ValidateIdentifier(Object e, String propertyName, String identifier) {
578             if (!CodeGenerator.IsValidLanguageIndependentIdentifier(identifier)) {
579                 String message = SR.GetString(SR.InvalidLanguageIdentifier, identifier, propertyName, e.GetType().FullName);
580                 throw new ArgumentException(message , "identifier");
581             }
582         }
583
584         private void ValidateExpression(CodeExpression e) {
585             if (e is CodeArrayCreateExpression) {
586                 ValidateArrayCreateExpression((CodeArrayCreateExpression)e);
587             }
588             else if (e is CodeBaseReferenceExpression) {
589                 ValidateBaseReferenceExpression((CodeBaseReferenceExpression)e);
590             }
591             else if (e is CodeBinaryOperatorExpression) {
592                 ValidateBinaryOperatorExpression((CodeBinaryOperatorExpression)e);
593             }
594             else if (e is CodeCastExpression) {
595                 ValidateCastExpression((CodeCastExpression)e);
596             }
597             else if (e is CodeDefaultValueExpression) {
598                 ValidateDefaultValueExpression((CodeDefaultValueExpression)e);
599             }
600             else if (e is CodeDelegateCreateExpression) {
601                 ValidateDelegateCreateExpression((CodeDelegateCreateExpression)e);
602             }
603             else if (e is CodeFieldReferenceExpression) {
604                 ValidateFieldReferenceExpression((CodeFieldReferenceExpression)e);
605             }
606             else if (e is CodeArgumentReferenceExpression) {
607                 ValidateArgumentReferenceExpression((CodeArgumentReferenceExpression)e);
608             }
609             else if (e is CodeVariableReferenceExpression) {
610                 ValidateVariableReferenceExpression((CodeVariableReferenceExpression)e);
611             }
612             else if (e is CodeIndexerExpression) {
613                 ValidateIndexerExpression((CodeIndexerExpression)e);
614             }
615             else if (e is CodeArrayIndexerExpression) {
616                 ValidateArrayIndexerExpression((CodeArrayIndexerExpression)e);
617             }
618             else if (e is CodeSnippetExpression) {
619                 ValidateSnippetExpression((CodeSnippetExpression)e);
620             }
621             else if (e is CodeMethodInvokeExpression) {
622                 ValidateMethodInvokeExpression((CodeMethodInvokeExpression)e);
623             }
624             else if (e is CodeMethodReferenceExpression) {
625                 ValidateMethodReferenceExpression((CodeMethodReferenceExpression)e);
626             }
627             else if (e is CodeEventReferenceExpression) {
628                 ValidateEventReferenceExpression((CodeEventReferenceExpression)e);
629             }
630             else if (e is CodeDelegateInvokeExpression) {
631                 ValidateDelegateInvokeExpression((CodeDelegateInvokeExpression)e);
632             }
633             else if (e is CodeObjectCreateExpression) {
634                 ValidateObjectCreateExpression((CodeObjectCreateExpression)e);
635             }
636             else if (e is CodeParameterDeclarationExpression) {
637                 ValidateParameterDeclarationExpression((CodeParameterDeclarationExpression)e);
638             }
639             else if (e is CodeDirectionExpression) {
640                 ValidateDirectionExpression((CodeDirectionExpression)e);
641             }
642             else if (e is CodePrimitiveExpression) {
643                 ValidatePrimitiveExpression((CodePrimitiveExpression)e);
644             }
645             else if (e is CodePropertyReferenceExpression) {
646                 ValidatePropertyReferenceExpression((CodePropertyReferenceExpression)e);
647             }
648             else if (e is CodePropertySetValueReferenceExpression) {
649                 ValidatePropertySetValueReferenceExpression((CodePropertySetValueReferenceExpression)e);
650             }
651             else if (e is CodeThisReferenceExpression) {
652                 ValidateThisReferenceExpression((CodeThisReferenceExpression)e);
653             }
654             else if (e is CodeTypeReferenceExpression) {
655                 ValidateTypeReference(((CodeTypeReferenceExpression)e).Type);
656             }
657             else if (e is CodeTypeOfExpression) {
658                 ValidateTypeOfExpression((CodeTypeOfExpression)e);
659             }
660             else {
661                 if (e == null) {
662                     throw new ArgumentNullException("e");
663                 }
664                 else {
665                     throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
666                 }
667             }
668         }
669
670         private void ValidateArrayCreateExpression(CodeArrayCreateExpression e) {
671             ValidateTypeReference(e.CreateType);
672             CodeExpressionCollection init = e.Initializers;
673             if (init.Count > 0) {
674                 ValidateExpressionList(init);
675             }
676             else {
677                 if (e.SizeExpression != null) {
678                     ValidateExpression(e.SizeExpression);
679                 }
680             }
681         }
682
683         private void ValidateBaseReferenceExpression(CodeBaseReferenceExpression e) { // Nothing to validate
684         }
685
686         private void ValidateBinaryOperatorExpression(CodeBinaryOperatorExpression e) {
687             ValidateExpression(e.Left);
688             ValidateExpression(e.Right);
689         }
690
691         private void ValidateCastExpression(CodeCastExpression e) {
692             ValidateTypeReference(e.TargetType);
693             ValidateExpression(e.Expression);
694         }
695
696         private static void ValidateDefaultValueExpression(CodeDefaultValueExpression e) {
697             ValidateTypeReference(e.Type);
698         }
699         
700         private void ValidateDelegateCreateExpression(CodeDelegateCreateExpression e) {
701             ValidateTypeReference(e.DelegateType);
702             ValidateExpression(e.TargetObject);
703             ValidateIdentifier(e,"MethodName",e.MethodName);
704         }
705
706         private void ValidateFieldReferenceExpression(CodeFieldReferenceExpression e) {
707             if (e.TargetObject != null) {
708                 ValidateExpression(e.TargetObject);
709             }
710             ValidateIdentifier(e,"FieldName",e.FieldName);
711         }
712
713         private static void ValidateArgumentReferenceExpression(CodeArgumentReferenceExpression e) {
714             ValidateIdentifier(e,"ParameterName",e.ParameterName);
715         }
716
717         private static void ValidateVariableReferenceExpression(CodeVariableReferenceExpression e) {
718             ValidateIdentifier(e,"VariableName",e.VariableName);
719         }
720
721         private void ValidateIndexerExpression(CodeIndexerExpression e) {
722             ValidateExpression(e.TargetObject);
723             foreach(CodeExpression exp in e.Indices) {            
724                 ValidateExpression(exp);
725             }
726         }
727
728         private void ValidateArrayIndexerExpression(CodeArrayIndexerExpression e) {
729             ValidateExpression(e.TargetObject);
730             foreach(CodeExpression exp in e.Indices) {            
731                 ValidateExpression(exp);
732             }
733         }
734
735         private void ValidateSnippetExpression(CodeSnippetExpression e) {
736         }
737
738         private void ValidateMethodInvokeExpression(CodeMethodInvokeExpression e) {
739             ValidateMethodReferenceExpression(e.Method);
740             ValidateExpressionList(e.Parameters);
741         }
742
743         private void ValidateMethodReferenceExpression(CodeMethodReferenceExpression e) {
744             if (e.TargetObject != null) {
745                 ValidateExpression(e.TargetObject);
746             }
747             ValidateIdentifier(e,"MethodName",e.MethodName);
748             ValidateTypeReferences(e.TypeArguments);
749         }
750
751         private void ValidateEventReferenceExpression(CodeEventReferenceExpression e) {
752            if (e.TargetObject != null) {
753                 ValidateExpression(e.TargetObject);
754            }
755            ValidateIdentifier(e,"EventName",e.EventName);
756         }
757
758         private void ValidateDelegateInvokeExpression(CodeDelegateInvokeExpression e) {
759            if (e.TargetObject != null) {
760                     ValidateExpression(e.TargetObject);
761            }
762            ValidateExpressionList(e.Parameters);
763         }
764
765         private void ValidateObjectCreateExpression(CodeObjectCreateExpression e) {
766             ValidateTypeReference(e.CreateType);
767             ValidateExpressionList(e.Parameters);
768         }
769
770         private void ValidateParameterDeclarationExpression(CodeParameterDeclarationExpression e) {
771            if (e.CustomAttributes.Count > 0) {
772                 ValidateAttributes(e.CustomAttributes);
773            }
774
775            ValidateTypeReference(e.Type);
776            ValidateIdentifier(e,"Name",e.Name);
777         }
778
779         private void ValidateDirectionExpression(CodeDirectionExpression e) {
780            ValidateExpression(e.Expression);
781         }
782
783         private void ValidatePrimitiveExpression(CodePrimitiveExpression e) {
784         }
785
786         private void ValidatePropertyReferenceExpression(CodePropertyReferenceExpression e) {
787            if (e.TargetObject != null) {
788               ValidateExpression(e.TargetObject);
789            }
790            ValidateIdentifier(e,"PropertyName",e.PropertyName);
791         }
792
793         private void ValidatePropertySetValueReferenceExpression(CodePropertySetValueReferenceExpression e) { // Do nothing
794         }
795
796         private void ValidateThisReferenceExpression(CodeThisReferenceExpression e) {  // Do nothing
797         }
798
799         private static void ValidateTypeOfExpression(CodeTypeOfExpression e) {
800             ValidateTypeReference(e.Type);
801         }
802
803         private static void ValidateCodeDirectives(CodeDirectiveCollection e) {
804             for (int i=0; i<e.Count; i++)
805                 ValidateCodeDirective(e[i]);
806         }
807
808         private static void ValidateCodeDirective(CodeDirective e) {
809             if (e is CodeChecksumPragma)
810                 ValidateChecksumPragma((CodeChecksumPragma) e);
811             else if (e is CodeRegionDirective)
812                 ValidateRegionDirective((CodeRegionDirective) e);
813             else
814                 throw new ArgumentException(SR.GetString(SR.InvalidElementType, e.GetType().FullName), "e");
815         }
816
817         private static void ValidateChecksumPragma(CodeChecksumPragma e) {
818             if (e.FileName.IndexOfAny(Path.GetInvalidPathChars()) != -1)
819                 throw new ArgumentException(SR.GetString(SR.InvalidPathCharsInChecksum, e.FileName));
820         }
821
822         private static void ValidateRegionDirective(CodeRegionDirective e) {
823             if (e.RegionText.IndexOfAny(newLineChars) != -1)
824                 throw new ArgumentException(SR.GetString(SR.InvalidRegion, e.RegionText));
825         }
826         
827         private bool IsCurrentInterface {
828             get {
829                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
830                     return currentClass.IsInterface;
831                 }
832                 return false;
833             }
834         }
835
836         private bool IsCurrentEnum {
837             get {
838                 if (currentClass != null && !(currentClass is CodeTypeDelegate)) {
839                     return currentClass.IsEnum;
840                 }
841                 return false;
842             }
843         }
844
845         private bool IsCurrentDelegate {
846             get {
847                 if (currentClass != null && currentClass is CodeTypeDelegate) {
848                     return true;
849                 }
850                 return false;
851             }
852         }
853
854         private CodeTypeDeclaration currentClass;
855     }
856 }