PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/3.1/Nov2013/tests/fsharp/tools/FSharp.PowerPack/fsppack/src/FSharp.Compiler.CodeDom/codedomvisitor.fs

#
F# | 101 lines | 78 code | 8 blank | 15 comment | 53 complexity | 7978fb2b7d9f88e6280eaad5b3ebb0e4 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0
  1. namespace Microsoft.Test.Compiler.CodeDom.Internal
  2. open System
  3. open System.IO
  4. open System.Text
  5. open System.Collections
  6. open System.CodeDom
  7. open System.CodeDom.Compiler
  8. open Microsoft.FSharp.Collections
  9. //---------------------------------------------------------------------------------------------
  10. // This module contains several utility functions for walking through CodeDom tree
  11. module Visitor =
  12. // Get all relevant CodeDom properties of an object
  13. // - more functions can return properties for one object because of class hierarchy
  14. let memberMap = [
  15. (fun (c:obj) -> match c with | :? CodeArrayCreateExpression as co -> [(co.CreateType:>obj); (co.Initializers:>obj); (co.SizeExpression:>obj);] | _ -> []);
  16. (fun (c:obj) -> match c with | :? CodeArrayIndexerExpression as co -> [(co.Indices:>obj); (co.TargetObject:>obj);] | _ -> []);
  17. (fun (c:obj) -> match c with | :? CodeAssignStatement as co -> [(co.Left:>obj); (co.Right:>obj);] | _ -> []);
  18. (fun (c:obj) -> match c with | :? CodeAttachEventStatement as co -> [(co.Event:>obj); (co.Listener:>obj);] | _ -> []);
  19. (fun (c:obj) -> match c with | :? CodeAttributeArgument as co -> [(co.Value:>obj);] | _ -> []);
  20. (fun (c:obj) -> match c with | :? CodeAttributeDeclaration as co -> [(co.AttributeType:>obj); (co.Arguments:>obj);] | _ -> []);
  21. (fun (c:obj) -> match c with | :? CodeBinaryOperatorExpression as co -> [(co.Left:>obj); (co.Operator:>obj); (co.Right:>obj);] | _ -> []);
  22. (fun (c:obj) -> match c with | :? CodeCastExpression as co -> [(co.Expression:>obj); (co.TargetType:>obj);] | _ -> []);
  23. (fun (c:obj) -> match c with | :? CodeCatchClause as co -> [(co.CatchExceptionType:>obj); (co.Statements:>obj);] | _ -> []);
  24. (fun (c:obj) -> match c with | :? CodeCommentStatement as co -> [(co.Comment:>obj);] | _ -> []);
  25. (fun (c:obj) -> match c with | :? CodeCompileUnit as co -> [(co.AssemblyCustomAttributes:>obj); (co.EndDirectives:>obj); (co.Namespaces:>obj); (co.StartDirectives:>obj);] | _ -> []);
  26. (fun (c:obj) -> match c with | :? CodeConditionStatement as co -> [(co.Condition:>obj); (co.FalseStatements:>obj); (co.TrueStatements:>obj);] | _ -> []);
  27. (fun (c:obj) -> match c with | :? CodeConstructor as co -> [(co.BaseConstructorArgs:>obj); (co.ChainedConstructorArgs:>obj);] | _ -> []);
  28. (fun (c:obj) -> match c with | :? CodeDefaultValueExpression as co -> [(co.Type:>obj);] | _ -> []);
  29. (fun (c:obj) -> match c with | :? CodeDelegateCreateExpression as co -> [(co.TargetObject:>obj); (co.DelegateType:>obj);] | _ -> []);
  30. (fun (c:obj) -> match c with | :? CodeDelegateInvokeExpression as co -> [(co.TargetObject:>obj); (co.Parameters:>obj);] | _ -> []);
  31. (fun (c:obj) -> match c with | :? CodeDirectionExpression as co -> [(co.Expression:>obj);] | _ -> []);
  32. (fun (c:obj) -> match c with | :? CodeEventReferenceExpression as co -> [(co.TargetObject:>obj);] | _ -> []);
  33. (fun (c:obj) -> match c with | :? CodeExpressionStatement as co -> [(co.Expression:>obj);] | _ -> []);
  34. (fun (c:obj) -> match c with | :? CodeFieldReferenceExpression as co -> [(co.TargetObject:>obj);] | _ -> []);
  35. (fun (c:obj) -> match c with | :? CodeIndexerExpression as co -> [(co.Indices:>obj); (co.TargetObject:>obj);] | _ -> []);
  36. (fun (c:obj) -> match c with | :? CodeIterationStatement as co -> [(co.IncrementStatement:>obj); (co.InitStatement:>obj); (co.Statements:>obj); (co.TestExpression:>obj);] | _ -> []);
  37. (fun (c:obj) -> match c with | :? CodeLabeledStatement as co -> [(co.Statement:>obj);] | _ -> []);
  38. (fun (c:obj) -> match c with | :? CodeMemberEvent as co -> [(co.ImplementationTypes:>obj); (co.PrivateImplementationType:>obj); (co.Type:>obj);] | _ -> []);
  39. (fun (c:obj) -> match c with | :? CodeMemberField as co -> [(co.InitExpression:>obj); (co.Type:>obj);] | _ -> []);
  40. (fun (c:obj) -> match c with | :? CodeMemberMethod as co -> [(co.ImplementationTypes:>obj); (co.Parameters:>obj); (co.PrivateImplementationType:>obj); (co.ReturnType:>obj); (co.ReturnTypeCustomAttributes:>obj); (co.Statements:>obj); (co.TypeParameters:>obj);] | _ -> []);
  41. (fun (c:obj) -> match c with | :? CodeMemberProperty as co -> [(co.GetStatements:>obj); (co.ImplementationTypes:>obj); (co.Parameters:>obj); (co.PrivateImplementationType:>obj); (co.SetStatements:>obj); (co.Type:>obj);] | _ -> []);
  42. (fun (c:obj) -> match c with | :? CodeMethodInvokeExpression as co -> [(co.Method:>obj); (co.Parameters:>obj);] | _ -> []);
  43. (fun (c:obj) -> match c with | :? CodeMethodReferenceExpression as co -> [(co.TargetObject:>obj); (co.TypeArguments:>obj);] | _ -> []);
  44. (fun (c:obj) -> match c with | :? CodeMethodReturnStatement as co -> [(co.Expression:>obj);] | _ -> []);
  45. (fun (c:obj) -> match c with | :? CodeNamespace as co -> [(co.Comments:>obj); (co.Imports:>obj); (co.Types:>obj);] | _ -> []);
  46. (fun (c:obj) -> match c with | :? CodeNamespaceImport as co -> [(co.LinePragma:>obj);] | _ -> []);
  47. (fun (c:obj) -> match c with | :? CodeObjectCreateExpression as co -> [(co.CreateType:>obj); (co.Parameters:>obj);] | _ -> []);
  48. (fun (c:obj) -> match c with | :? CodeParameterDeclarationExpression as co -> [(co.CustomAttributes:>obj); (co.Direction:>obj); (co.Type:>obj);] | _ -> []);
  49. (fun (c:obj) -> match c with | :? CodePropertyReferenceExpression as co -> [(co.TargetObject:>obj);] | _ -> []);
  50. (fun (c:obj) -> match c with | :? CodeRemoveEventStatement as co -> [(co.Event:>obj); (co.Listener:>obj);] | _ -> []);
  51. (fun (c:obj) -> match c with | :? CodeStatement as co -> [(co.EndDirectives:>obj); (co.StartDirectives:>obj); (co.LinePragma:>obj);] | _ -> []);
  52. (fun (c:obj) -> match c with | :? CodeThrowExceptionStatement as co -> [(co.ToThrow:>obj);] | _ -> []);
  53. (fun (c:obj) -> match c with | :? CodeTryCatchFinallyStatement as co -> [(co.CatchClauses:>obj); (co.FinallyStatements:>obj); (co.TryStatements:>obj);] | _ -> []);
  54. (fun (c:obj) -> match c with | :? CodeTypeDeclaration as co -> [(co.BaseTypes:>obj); (co.Members:>obj); (co.TypeAttributes:>obj); (co.TypeParameters:>obj);] | _ -> []);
  55. (fun (c:obj) -> match c with | :? CodeTypeDelegate as co -> [(co.Parameters:>obj); (co.ReturnType:>obj);] | _ -> []);
  56. (fun (c:obj) -> match c with | :? CodeTypeMember as co -> [(co.Attributes:>obj); (co.Comments:>obj); (co.CustomAttributes:>obj); (co.EndDirectives:>obj); (co.LinePragma:>obj); (co.StartDirectives:>obj);] | _ -> []);
  57. (fun (c:obj) -> match c with | :? CodeTypeOfExpression as co -> [(co.Type:>obj);] | _ -> []);
  58. (fun (c:obj) -> match c with | :? CodeTypeParameter as co -> [(co.Constraints:>obj); (co.CustomAttributes:>obj);] | _ -> []);
  59. (fun (c:obj) -> match c with | :? CodeTypeReference as co -> [(co.ArrayElementType:>obj); (co.TypeArguments:>obj);] | _ -> []);
  60. (fun (c:obj) -> match c with | :? CodeTypeReferenceExpression as co -> [(co.Type:>obj);] | _ -> []);
  61. (fun (c:obj) -> match c with | :? CodeVariableDeclarationStatement as co -> [(co.InitExpression:>obj); (co.Type:>obj);] | _ -> []) ];
  62. let children o = memberMap |> Seq.collect (fun e -> e o)
  63. let rec codeDomFold' f st o =
  64. match box o with
  65. | :? CollectionBase as cl ->
  66. cl |> Seq.cast |> Seq.fold (codeDomFold' f) st;
  67. | _ ->
  68. let (nst,recurse) = f st o;
  69. if (recurse) then
  70. o |> children |> Seq.fold (codeDomFold' f) nst;
  71. else nst
  72. let codeDomCallbackWithScope' f =
  73. let rec callback oscope res o =
  74. match box o with
  75. | :? CollectionBase as cl ->
  76. cl |> Seq.cast |> Seq.fold (f callback oscope) res;
  77. | _ ->
  78. o |> children |> Seq.fold (f callback oscope) res;
  79. f callback;
  80. /// Search for members and return flat list of selected members
  81. /// Function given as an argument returns tuple - first item specifies
  82. /// if the current element should be included in the result, the second
  83. /// specifies if we should walk through child members of the current object
  84. let codeDomFlatFilter f o = codeDomFold' ( fun st o -> let (inc,rc) = (f o) in if (inc) then (o::st,rc) else (st,rc) ) [] (box o)
  85. /// Walks through the CodeDom tree and keeps current "scope" and the result.
  86. /// The result is collected through entire tree, but the modified scope is
  87. /// passed only to sub-nodes of the current node.
  88. ///
  89. /// First argument is a function that is called for nodes and has a
  90. /// function as a first argument, scope and result as a second and current node as a third.
  91. /// The function argument can be used to walk deeper in the tree if wanted.
  92. let codeDomCallbackWithScope f scope st o = codeDomCallbackWithScope' f scope st (box o)
  93. let codeDomCallBackNoScope f st o = codeDomCallbackWithScope (fun rcall () res x -> f (rcall ()) res x) () st o