The base architecture for code-contracts analysis
[mono.git] / mcs / class / Mono.CodeContracts / Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths / PathExtensions.cs
1 // 
2 // PathExtensions.cs
3 // 
4 // Authors:
5 //      Alexander Chebaturkin (chebaturkin@gmail.com)
6 // 
7 // Copyright (C) 2011 Alexander Chebaturkin
8 // 
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //  
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Collections.Generic;
30 using System.Linq;
31 using System.Text;
32 using Mono.CodeContracts.Static.AST;
33 using Mono.CodeContracts.Static.DataStructures;
34
35 namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths {
36         static class PathExtensions {
37                 public static HashSet<Field> FieldsIn (this LispList<PathElement> path)
38                 {
39                         var result = new HashSet<Field> ();
40                         if (path != null) {
41                                 foreach (PathElement element in path.AsEnumerable ()) {
42                                         Field f;
43                                         if (element.TryField (out f))
44                                                 result.Add (f);
45                                 }
46                         }
47                         return result;
48                 }
49
50                 public static string ToCodeString (this PathElement[] path)
51                 {
52                         return PathToString (path);
53                 }
54
55                 public static string ToCodeString (this LispList<PathElement> path)
56                 {
57                         return PathToString (path.AsEnumerable ());
58                 }
59
60                 private static string PathToString (IEnumerable<PathElement> path)
61                 {
62                         bool first = true;
63                         bool isReference = false;
64                         bool isUnmanagedPointer = false;
65                         var sb = new StringBuilder ();
66
67                         List<PathElement> pathL = path.ToList ();
68
69                         for (int i = 0; i < pathL.Count; i++) {
70                                 PathElement element = pathL [i];
71                                 if (element.IsMethodCall && !element.IsGetter && element.IsStatic) {
72                                         string oldString = sb.ToString ();
73                                         sb = new StringBuilder ();
74                                         sb.AppendFormat ("{0}({1})", element, oldString);
75                                 } else {
76                                         if (!string.IsNullOrEmpty (element.CastTo)) {
77                                                 string oldString = sb.ToString ();
78                                                 sb = new StringBuilder ();
79                                                 sb.AppendFormat ("(({0}{1}){2})", element.CastTo, isUnmanagedPointer ? "*" : "", oldString);
80                                         }
81
82                                         sb.Append (isUnmanagedPointer ? "->" : ".");
83                                         sb.Append (element.ToString ());
84                                         if (element.IsMethodCall && !element.IsGetter)
85                                                 sb.Append ("()");
86                                 }
87                                 if (first)
88                                         first = false;
89
90                                 int num = (element.IsAddressOf ? 1 : 0) + (element.IsUnmanagedPointer ? 1 : 0) + (element.IsManagedPointer ? 1 : 0);
91                                 isUnmanagedPointer = element.IsUnmanagedPointer;
92
93                                 for (int j = 0; j < num; j++) {
94                                         if (j + 1 < pathL.Count) {
95                                                 if (pathL [j + 1].IsDeref)
96                                                         ++j;
97                                         } else
98                                                 isReference = true;
99                                 }
100                         }
101
102                         if (isReference)
103                                 return isUnmanagedPointer ? sb.ToString () : "&" + sb;
104                         if (isUnmanagedPointer)
105                                 return "*" + sb;
106
107                         return sb.ToString ();
108                 }
109         }
110 }