5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2011 Alexander Chebaturkin
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System.Collections.Generic;
31 using Mono.CodeContracts.Static.AST;
33 namespace Mono.CodeContracts.Static.ContractExtraction {
34 static class HelperMethods {
35 public static Method IsMethodCall (Statement s)
40 var expressionStatement = s as ExpressionStatement;
41 if (expressionStatement == null)
44 var methodCall = expressionStatement.Expression as MethodCall;
45 if (methodCall == null)
48 var binding = methodCall.Callee as MemberBinding;
52 return binding.BoundMember as Method;
55 public static Local ExtractPreamble (Method method, ContractNodes contractNodes, Block contractInitializer, out Block postPreamble)
61 public static List<Statement> ExtractContractBlocks (List<Statement> blocks, int firstBlockIndex, int firstStmtIndex, int lastBlockIndex, int lastStmtIndex)
63 var result = new List<Statement> ();
64 var firstBlock = (Block) blocks [firstBlockIndex];
65 var block = new Block (new List<Statement> ());
66 if (firstBlock != null) {
67 int cnt = firstBlockIndex == lastBlockIndex ? lastStmtIndex + 1 : firstBlock.Statements.Count;
68 for (int i = firstStmtIndex; i < cnt; i++) {
69 Statement stmt = firstBlock.Statements [i];
70 block.Statements.Add (stmt);
72 firstBlock.Statements [i] = null;
76 int nextIndex = firstBlockIndex + 1;
77 if (nextIndex > lastBlockIndex)
79 Block newLastBlock = null;
80 int lastFullBlockIndex = lastBlockIndex - 1;
81 var lastBlock = (Block) blocks [lastBlockIndex];
82 if (lastBlock != null && lastStmtIndex == lastBlock.Statements.Count - 1)
83 lastFullBlockIndex = lastBlockIndex;
85 newLastBlock = new Block (new List<Statement> ());
86 if (block.Statements != null && block.Statements.Count > 0) {
87 var branch = block.Statements [block.Statements.Count - 1] as Branch;
88 if (branch != null && branch.Target != null && branch.Target == lastBlock)
89 branch.Target = newLastBlock;
93 for (; nextIndex < lastFullBlockIndex; ++nextIndex) {
94 var curBlock = (Block) blocks [nextIndex];
95 result.Add (curBlock);
96 if (curBlock != null) {
97 blocks [nextIndex] = null;
98 if (newLastBlock != null && curBlock.Statements != null && curBlock.Statements.Count > 0) {
99 var branch = curBlock.Statements [curBlock.Statements.Count - 1] as Branch;
100 if (branch != null && branch.Target != null && branch.Target == lastBlock)
101 branch.Target = newLastBlock;
106 if (newLastBlock != null) {
107 for (int i = 0; i < lastStmtIndex + 1; i++) {
108 newLastBlock.Statements.Add (lastBlock.Statements [i]);
109 lastBlock.Statements [i] = null;
112 result.Add (newLastBlock);
117 public static bool IsCompilerGenerated (TypeNode type)
119 throw new NotImplementedException ();
122 public static int FindNextRealStatement (List<Statement> stmts, int beginIndex)
124 if (stmts == null || stmts.Count <= beginIndex)
126 int index = beginIndex;
127 while (index < stmts.Count && (stmts [index] == null || stmts [index].NodeType == NodeType.Nop))
132 public static bool IsReferenceAsVisibleAs (Member member, Member asThisMember)
134 var type = member as TypeNode;
136 return IsTypeAsVisibleAs (type, asThisMember);
137 var method = member as Method;
139 if (method != null) {
140 if (method.HasGenericParameters)
141 throw new NotImplementedException ();
144 member1 = Unspecialize (member);
146 return IsDefinitionAsVisibleAs (member1, asThisMember);
149 private static bool IsDefinitionAsVisibleAs (this Member member, Member asThisMember)
151 Module memberModule = member.Module;
152 Module asThisMemberModule = asThisMember.Module;
154 for (Member mbr = member; mbr != null; mbr = mbr.DeclaringType) {
156 bool visible = false;
157 for (Member mbr1 = asThisMember; mbr1 != null; mbr1 = mbr1.DeclaringType) {
158 if (mbr1.IsAssembly) {
159 if ((mbr1.IsPrivate || mbr1.IsAssembly) && memberModule == asThisMemberModule)
161 } else if (mbr1.IsFamily) {
163 if (IsInsideOf (mbr, mbr1) || IsInsideSubclass (mbr, mbr1.DeclaringType))
165 } else if (mbr.IsFamily && (mbr.DeclaringType == mbr1.DeclaringType || IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType)))
167 } else if (mbr1.IsFamilyOrAssembly) {
169 if (memberModule == asThisMemberModule || IsInsideSubclass (mbr, mbr1.DeclaringType))
171 } else if (mbr.IsAssembly) {
172 if (memberModule == asThisMemberModule)
174 } else if (mbr.IsFamily) {
175 if (IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType))
177 } else if (mbr.IsFamilyOrAssembly && memberModule == asThisMemberModule && IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType))
179 } else if (mbr1.IsPrivate && mbr.IsPrivate && IsInsideOf (mbr, mbr1.DeclaringType))
189 private static bool IsSubclassOf (this TypeNode thisType, TypeNode thatType)
191 if (thatType == null)
193 return thisType.IsAssignableTo (thatType);
196 private static bool IsInsideSubclass (this Member member, Member thatValue)
198 var targetType = thatValue as TypeNode;
199 if (targetType == null)
202 for (TypeNode declaringType = member.DeclaringType; declaringType != null; declaringType = declaringType.DeclaringType) {
203 if (declaringType.IsAssignableTo (targetType))
209 private static bool IsInsideOf (this Member thisValue, Member thatValue)
211 var typeNode = thatValue as TypeNode;
212 if (typeNode == null)
214 for (TypeNode declaringType = thisValue.DeclaringType; declaringType != null; declaringType = declaringType.DeclaringType) {
215 if (declaringType == typeNode)
221 private static Member Unspecialize (Member member)
226 private static bool IsTypeAsVisibleAs (this TypeNode type, Member asThisMember)
231 switch (type.NodeType) {
232 case NodeType.Reference:
233 return ((Reference) type).ElementType.IsTypeAsVisibleAs (asThisMember);
235 if (type.HasGenericParameters)
236 throw new NotImplementedException ();
238 return IsDefinitionAsVisibleAs (type, asThisMember);
242 public static bool IsVisibleFrom (this TypeNode type, TypeNode from)
244 TypeNode declaringType = type.DeclaringType;
245 if (declaringType != null) {
246 if (IsContainedIn (from, declaringType) || IsInheritedFrom (from, type))
248 if (type.IsNestedFamily)
249 return IsInheritedFrom (from, declaringType);
250 if (type.IsNestedPublic)
251 return IsVisibleFrom (declaringType, from);
252 if (type.IsNestedInternal) {
253 if (IsInheritedFrom (from, declaringType))
255 if (declaringType.Module == from.Module)
256 return IsVisibleFrom (declaringType, from);
260 if (type.IsNestedFamilyAndAssembly)
261 return from.Module == declaringType.Module && IsInheritedFrom (from, declaringType);
262 if ((type.IsAssembly || type.IsNestedAssembly) && declaringType.Module == from.Module)
263 return IsVisibleFrom (declaringType, from);
268 return type.Module == from.Module || type.IsPublic;
271 public static bool IsVisibleFrom (this Member member, TypeNode from)
273 var type = member as TypeNode;
275 return type.IsVisibleFrom (from);
277 TypeNode declaringType = member.DeclaringType;
278 if (from.IsContainedIn (declaringType))
281 return declaringType.IsVisibleFrom (from);
283 return from.IsInheritedFrom (declaringType);
284 if (member.IsFamilyAndAssembly)
285 return from.Module == declaringType.Module && from.IsInheritedFrom (declaringType);
286 if (member.IsFamilyOrAssembly) {
287 if (from.IsInheritedFrom (declaringType))
289 if (from.Module == declaringType.Module)
290 return declaringType.IsVisibleFrom (from);
295 return member.IsAssembly && declaringType.Module == from.Module && declaringType.IsVisibleFrom (from);
298 public static bool IsInheritedFrom (this TypeNode type, TypeNode from)
301 if (type.HasBaseClass (out baseClass)) {
302 if (baseClass == from || baseClass.IsInheritedFrom (from))
309 private static bool HasBaseClass (this TypeNode type, out TypeNode baseClass)
311 var clazz = type as Class;
312 if (clazz != null && clazz.BaseType != null) {
313 baseClass = clazz.BaseType;
317 baseClass = default(TypeNode);
321 public static bool IsContainedIn (this TypeNode inner, TypeNode outer)
326 if (inner.DeclaringType != null)
327 return inner.DeclaringType.IsContainedIn (outer);