1 // 2 // MetaDataProvider.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; 30 using System.Collections.Generic; 31 using System.Linq; 32 using Mono.Cecil; 33 using Mono.CodeContracts.Static.AST; 34 using Mono.CodeContracts.Static.AST.Visitors; 35 using Mono.CodeContracts.Static.ContractExtraction; 36 using Mono.CodeContracts.Static.DataStructures; 37 38 namespace Mono.CodeContracts.Static.Providers { 39 class MetaDataProvider : IMetaDataProvider { 40 public static readonly MetaDataProvider Instance = new MetaDataProvider (); 41 42 #region IMetaDataProvider Members AccessMethodBody(Method method, IMethodCodeConsumer<Data, Result> consumer, Data data)43 public Result AccessMethodBody<Data, Result> (Method method, IMethodCodeConsumer<Data, Result> consumer, Data data) 44 { 45 return consumer.Accept (CodeProviderImpl.Instance, CodeProviderImpl.Instance.Entry (method), method, data); 46 } 47 IsReferenceType(TypeNode type)48 public bool IsReferenceType (TypeNode type) 49 { 50 return (!type.IsValueType); 51 } 52 DeclaringMethod(Parameter parameter)53 public Method DeclaringMethod (Parameter parameter) 54 { 55 return parameter.DeclaringMethod; 56 } 57 ParameterIndex(Parameter parameter)58 public int ParameterIndex (Parameter parameter) 59 { 60 return parameter.Index; 61 } 62 IsVoidMethod(Method method)63 public bool IsVoidMethod (Method method) 64 { 65 return IsVoid (method.ReturnType); 66 } 67 TryLoadAssembly(string filename, out AssemblyNode assembly, out string reasonOfFailure)68 public bool TryLoadAssembly (string filename, out AssemblyNode assembly, out string reasonOfFailure) 69 { 70 assembly = AssemblyNode.ReadAssembly (filename); 71 if (!TryLoadContractNodes (ref assembly)) { 72 reasonOfFailure = "Couldn't find CodeContracts assembly in referencing assemblies"; 73 return false; 74 } 75 reasonOfFailure = null; 76 return true; 77 } 78 ReturnType(Method method)79 public TypeNode ReturnType (Method method) 80 { 81 return method.ReturnType; 82 } 83 Parameters(Method method)84 public IIndexable<Parameter> Parameters (Method method) 85 { 86 return new Indexable<Parameter> (method.Parameters); 87 } 88 This(Method method)89 public Parameter This (Method method) 90 { 91 return method.ThisParameter; 92 } 93 Name(Method method)94 public string Name (Method method) 95 { 96 return method.Name; 97 } 98 Name(Field field)99 public string Name (Field field) 100 { 101 return field.Name; 102 } 103 Name(TypeNode type)104 public string Name (TypeNode type) 105 { 106 return type.Name; 107 } 108 FieldType(Field field)109 public TypeNode FieldType (Field field) 110 { 111 return field.FieldType; 112 } 113 FullName(Method method)114 public string FullName (Method method) 115 { 116 return method.FullName; 117 } 118 FullName(TypeNode type)119 public string FullName (TypeNode type) 120 { 121 return type.FullName; 122 } 123 DeclaringType(Field field)124 public TypeNode DeclaringType (Field field) 125 { 126 return field.DeclaringType; 127 } 128 IsMain(Method method)129 public bool IsMain (Method method) 130 { 131 MethodDefinition entryPoint = method.Definition.Module.EntryPoint; 132 133 return entryPoint != null && entryPoint.Equals (method); 134 } 135 IsStatic(Method method)136 public bool IsStatic (Method method) 137 { 138 return method.IsStatic; 139 } 140 IsStatic(Field field)141 public bool IsStatic (Field field) 142 { 143 return field.IsStatic; 144 } 145 IsPrivate(Method method)146 public bool IsPrivate (Method method) 147 { 148 return method.IsPrivate; 149 } 150 IsProtected(Method method)151 public bool IsProtected (Method method) 152 { 153 return method.IsProtected; 154 } 155 IsPublic(Method method)156 public bool IsPublic (Method method) 157 { 158 return method.IsPublic; 159 } 160 IsVirtual(Method method)161 public bool IsVirtual (Method method) 162 { 163 return method.IsVirtual; 164 } 165 IsNewSlot(Method method)166 public bool IsNewSlot (Method method) 167 { 168 return method.IsNewSlot; 169 } 170 IsOverride(Method method)171 public bool IsOverride (Method method) 172 { 173 return !method.IsNewSlot && method.HasOverrides; 174 } 175 IsFinal(Method method)176 public bool IsFinal (Method method) 177 { 178 return method.IsFinal; 179 } 180 IsConstructor(Method method)181 public bool IsConstructor (Method method) 182 { 183 return method.IsConstructor; 184 } 185 IsAbstract(Method method)186 public bool IsAbstract (Method method) 187 { 188 return method.IsAbstract; 189 } 190 IsPropertySetter(Method method, out Property property)191 public bool IsPropertySetter (Method method, out Property property) 192 { 193 //todo: implement this 194 195 property = null; 196 return false; 197 } 198 IsPropertyGetter(Method method, out Property property)199 public bool IsPropertyGetter (Method method, out Property property) 200 { 201 //todo: implement this 202 203 property = null; 204 return false; 205 } 206 DeclaringType(Method method)207 public TypeNode DeclaringType (Method method) 208 { 209 return method.DeclaringType; 210 } 211 HasBody(Method method)212 public bool HasBody (Method method) 213 { 214 return method.HasBody; 215 } 216 DerivesFrom(TypeNode sub, TypeNode type)217 public bool DerivesFrom (TypeNode sub, TypeNode type) 218 { 219 return sub.IsAssignableTo (type); 220 } 221 Equal(TypeNode type, TypeNode otherType)222 public bool Equal (TypeNode type, TypeNode otherType) 223 { 224 return type == otherType; 225 } 226 TryGetImplementingMethod(TypeNode type, Method calledMethod, out Method implementingMethod)227 public bool TryGetImplementingMethod (TypeNode type, Method calledMethod, out Method implementingMethod) 228 { 229 //todo: implement this 230 implementingMethod = null; 231 return false; 232 } 233 Unspecialized(Method method)234 public Method Unspecialized (Method method) 235 { 236 if (method.HasGenericParameters) 237 throw new NotImplementedException (); 238 239 return method; 240 } 241 OverridenAndImplementedMethods(Method method)242 public IEnumerable<Method> OverridenAndImplementedMethods (Method method) 243 { 244 //todo: implement this 245 yield break; 246 } 247 ManagedPointer(TypeNode type)248 public TypeNode ManagedPointer (TypeNode type) 249 { 250 return type.GetReferenceType (); 251 } 252 TryGetRootMethod(Method method, out Method rootMethod)253 public bool TryGetRootMethod (Method method, out Method rootMethod) 254 { 255 //todo: implement this 256 rootMethod = method; 257 return true; 258 } 259 ImplementedMethods(Method method)260 public IEnumerable<Method> ImplementedMethods (Method method) 261 { 262 yield break; 263 } 264 IsAutoPropertyMember(Method method)265 public bool IsAutoPropertyMember (Method method) 266 { 267 //todo: implement this 268 return false; 269 } 270 IsFinalizer(Method method)271 public bool IsFinalizer (Method method) 272 { 273 return "Finalize" == method.Name; 274 } 275 IsDispose(Method method)276 public bool IsDispose (Method method) 277 { 278 if (method.Name != "Dispose" && method.Name != "System.IDisposable.Dispose") 279 return false; 280 if (method.Parameters == null || method.Parameters.Count == 0) 281 return true; 282 if (method.Parameters.Count == 1) 283 return Equal(method.Parameters [0].Type, CoreSystemTypes.Instance.TypeBoolean); 284 285 return false; 286 } 287 #endregion 288 289 #region Implementation of IMetaDataProvider<Local,Parameter,Method,FieldReference,PropertyReference,EventReference,TypeNode,Attribute,AssemblyNode> 290 291 public TypeNode System_Single 292 { 293 get { return CoreSystemTypes.Instance.TypeSingle; } 294 } 295 296 public TypeNode System_Double 297 { 298 get { return CoreSystemTypes.Instance.TypeDouble; } 299 } 300 301 public TypeNode System_Type 302 { 303 get { return CoreSystemTypes.Instance.TypeSystemType; } 304 } 305 306 public TypeNode System_Char 307 { 308 get { return CoreSystemTypes.Instance.TypeChar; } 309 } 310 311 public TypeNode System_Int32 312 { 313 get { return CoreSystemTypes.Instance.TypeInt32; } 314 } 315 316 public TypeNode System_String 317 { 318 get { return CoreSystemTypes.Instance.TypeString; } 319 } 320 321 public TypeNode System_Boolean 322 { 323 get { return CoreSystemTypes.Instance.TypeBoolean; } 324 } 325 326 public TypeNode System_IntPtr 327 { 328 get { return CoreSystemTypes.Instance.TypeIntPtr; } 329 } 330 331 public TypeNode System_UIntPtr 332 { 333 get { return CoreSystemTypes.Instance.TypeUIntPtr; } 334 } 335 336 public TypeNode System_Void 337 { 338 get { return CoreSystemTypes.Instance.TypeVoid; } 339 } 340 341 public TypeNode System_Array 342 { 343 get { return CoreSystemTypes.Instance.TypeArray; } 344 } 345 346 public TypeNode System_Object 347 { 348 get { return CoreSystemTypes.Instance.TypeObject; } 349 } 350 351 public TypeNode System_Int8 352 { 353 get { return CoreSystemTypes.Instance.TypeSByte; } 354 } 355 356 public TypeNode System_Int64 357 { 358 get { return CoreSystemTypes.Instance.TypeInt64; } 359 } 360 361 public TypeNode System_Int16 362 { 363 get { return CoreSystemTypes.Instance.TypeInt16; } 364 } 365 366 public TypeNode System_UInt8 367 { 368 get { return CoreSystemTypes.Instance.TypeByte; } 369 } 370 371 public TypeNode System_UInt64 372 { 373 get { return CoreSystemTypes.Instance.TypeUInt64; } 374 } 375 376 public TypeNode System_UInt32 377 { 378 get { return CoreSystemTypes.Instance.TypeUInt32; } 379 } 380 381 public TypeNode System_UInt16 382 { 383 get { return CoreSystemTypes.Instance.TypeUInt16; } 384 } 385 Methods(AssemblyNode assembly)386 public IEnumerable<Method> Methods (AssemblyNode assembly) 387 { 388 return assembly.Modules.SelectMany (a => a.Types).SelectMany (t => t.Methods); 389 } 390 Name(Parameter parameter)391 public string Name (Parameter parameter) 392 { 393 return parameter.Name; 394 } 395 ParameterType(Parameter parameter)396 public TypeNode ParameterType (Parameter parameter) 397 { 398 return parameter.Type; 399 } 400 LocalType(Local local)401 public TypeNode LocalType (Local local) 402 { 403 return local.Type; 404 } 405 IsStruct(TypeNode type)406 public bool IsStruct (TypeNode type) 407 { 408 return type.IsValueType; 409 } 410 Unspecialized(Field field)411 public Field Unspecialized (Field field) 412 { 413 return field; 414 } 415 IsManagedPointer(TypeNode value)416 public bool IsManagedPointer (TypeNode value) 417 { 418 return value is Reference; 419 } 420 IsArray(TypeNode type)421 public bool IsArray (TypeNode type) 422 { 423 return type.IsArray; 424 } 425 Interfaces(TypeNode type)426 public IEnumerable<TypeNode> Interfaces (TypeNode type) 427 { 428 return type.Interfaces; 429 } 430 TryGetSystemType(string fullName, out TypeNode type)431 public bool TryGetSystemType (string fullName, out TypeNode type) 432 { 433 int len = fullName.LastIndexOf ("."); 434 string ns = ""; 435 string className = fullName; 436 if (len > 0) { 437 ns = fullName.Substring (0, len); 438 className = fullName.Substring (len + 1); 439 } 440 type = CoreSystemTypes.Instance.SystemAssembly.GetType (ns, className); 441 return type != null; 442 } 443 IsInterface(TypeNode type)444 public bool IsInterface (TypeNode type) 445 { 446 return type.IsInterface; 447 } 448 Properties(TypeNode type)449 public IEnumerable<Property> Properties (TypeNode type) 450 { 451 return type.Properties; 452 } 453 IsStatic(Property property)454 public bool IsStatic (Property property) 455 { 456 return property.IsStatic; 457 } 458 IsAsVisibleAs(Field value, Method method)459 public bool IsAsVisibleAs (Field value, Method method) 460 { 461 return HelperMethods.IsReferenceAsVisibleAs (value, method); 462 } 463 IsAsVisibleAs(Method value, Method method)464 public bool IsAsVisibleAs (Method value, Method method) 465 { 466 return HelperMethods.IsReferenceAsVisibleAs (value, method); 467 } 468 IsVisibleFrom(Field field, TypeNode declaringType)469 public bool IsVisibleFrom (Field field, TypeNode declaringType) 470 { 471 return field.IsVisibleFrom (declaringType); 472 } 473 IsVisibleFrom(Method value, TypeNode declaringType)474 public bool IsVisibleFrom (Method value, TypeNode declaringType) 475 { 476 return value.IsVisibleFrom (declaringType); 477 } 478 Equal(Method thisMethod, Method thatMethod)479 public bool Equal (Method thisMethod, Method thatMethod) 480 { 481 return thisMethod == thatMethod; 482 } 483 Locals(Method method)484 public IIndexable<Local> Locals (Method method) 485 { 486 return new Indexable<Local> (method.Locals); 487 } 488 ElementType(TypeNode type)489 public TypeNode ElementType (TypeNode type) 490 { 491 var reference = type as Reference; 492 if (reference != null) 493 return reference.ElementType; 494 //todo: array 495 496 throw new NotImplementedException (); 497 } 498 Unspecialized(TypeNode type)499 public TypeNode Unspecialized (TypeNode type) 500 { 501 return type; 502 } 503 IsProtected(Field field)504 public bool IsProtected (Field field) 505 { 506 return field.IsFamily || field.IsFamilyAndAssembly || field.IsFamilyOrAssembly; 507 } 508 IsPublic(Field field)509 public bool IsPublic (Field field) 510 { 511 return field.IsPublic; 512 } 513 ParameterStackIndex(Parameter parameter)514 public int ParameterStackIndex (Parameter parameter) 515 { 516 Method declaringMethod = parameter.DeclaringMethod; 517 return declaringMethod.Parameters.Count + (declaringMethod.IsStatic ? 0 : 1) - parameter.Index - 1; 518 } 519 HasGetter(Property property, out Method method)520 public bool HasGetter (Property property, out Method method) 521 { 522 if (property.HasGetter) { 523 method = property.Getter; 524 return true; 525 } 526 method = null; 527 return false; 528 } 529 HasSetter(Property property, out Method method)530 public bool HasSetter (Property property, out Method method) 531 { 532 if (property.HasSetter) { 533 method = property.Setter; 534 return true; 535 } 536 method = null; 537 return false; 538 } 539 IsReadonly(Field value)540 public bool IsReadonly (Field value) 541 { 542 return value.IsReadonly; 543 } 544 HasValueRepresentation(TypeNode type)545 public bool HasValueRepresentation (TypeNode type) 546 { 547 return !IsStruct (type) || IsPrimitive (type) || IsEnum (type); 548 } 549 IsVoid(TypeNode type)550 public bool IsVoid (TypeNode type) 551 { 552 return type.Equals (System_Void); 553 } 554 IsSpecialized(Method calledMethod, ref IImmutableMap<TypeNode, TypeNode> specialization)555 public void IsSpecialized (Method calledMethod, ref IImmutableMap<TypeNode, TypeNode> specialization) 556 { 557 throw new NotImplementedException (); 558 } 559 Fields(TypeNode type)560 public IEnumerable<Field> Fields (TypeNode type) 561 { 562 return type.Fields; 563 } 564 IsOut(Parameter p)565 public bool IsOut (Parameter p) 566 { 567 return p.IsOut; 568 } 569 IsPrimitive(TypeNode type)570 public bool IsPrimitive (TypeNode type) 571 { 572 return type.IsPrimitive; 573 } 574 IsClass(TypeNode type)575 public bool IsClass (TypeNode type) 576 { 577 return type.IsClass; 578 } 579 IsVisibleFrom(TypeNode type, TypeNode fromType)580 public bool IsVisibleFrom (TypeNode type, TypeNode fromType) 581 { 582 return type.IsVisibleFrom (fromType); 583 } 584 IsCompilerGenerated(Method method)585 public bool IsCompilerGenerated (Method method) 586 { 587 return method.IsCompilerGenerated; 588 } 589 IsSpecialized(Method method)590 public bool IsSpecialized (Method method) 591 { 592 return false; 593 } 594 IsFormalTypeParameter(TypeNode type)595 public bool IsFormalTypeParameter (TypeNode type) 596 { 597 return false; 598 } 599 IsMethodFormalTypeParameter(TypeNode type)600 public bool IsMethodFormalTypeParameter (TypeNode type) 601 { 602 return false; 603 } 604 ArrayType(TypeNode type, int rank)605 public TypeNode ArrayType (TypeNode type, int rank) 606 { 607 return type.GetArrayType (rank); 608 } 609 IsCompilerGenerated(Field field)610 public bool IsCompilerGenerated (Field field) 611 { 612 return field.IsCompilerGenerated; 613 } 614 TypeSize(TypeNode type)615 public int TypeSize (TypeNode type) 616 { 617 int classSize = type.ClassSize; 618 if (classSize > 0) 619 return classSize; 620 int size = TypeSizeHelper (type); 621 type.ClassSize = size; 622 return size; 623 } 624 Name(Local local)625 public string Name (Local local) 626 { 627 return local.Name; 628 } 629 TypeSizeHelper(TypeNode type)630 private int TypeSizeHelper (TypeNode type) 631 { 632 if (IsManagedPointer (type)) 633 return 4; 634 if (type == System_Boolean) 635 return 1; 636 if (type == System_Char) 637 return 2; 638 if (type == System_Int8) 639 return 1; 640 if (type == System_Int16) 641 return 2; 642 if (type == System_Int32) 643 return 4; 644 if (type == System_Int64) 645 return 8; 646 if (type == System_IntPtr || type == System_Object || type == System_String || type == System_Type) 647 return 4; 648 649 if (type == System_UInt8) 650 return 1; 651 if (type == System_UInt16) 652 return 2; 653 if (type == System_UInt32) 654 return 4; 655 if (type == System_UInt64) 656 return 8; 657 658 if (type == System_UIntPtr || type == System_Single) 659 return 4; 660 if (type == System_Double) 661 return 8; 662 663 return -1; 664 } 665 IsEnum(TypeNode type)666 private bool IsEnum (TypeNode type) 667 { 668 return type.IsEnum; 669 } 670 #endregion 671 TryLoadContractNodes(ref AssemblyNode assembly)672 private bool TryLoadContractNodes (ref AssemblyNode assembly) 673 { 674 ContractNodes nodes = null; 675 foreach (Module module in assembly.Modules) { 676 IAssemblyResolver assemblyResolver = module.Definition.AssemblyResolver; 677 foreach (AssemblyNameReference reference in module.Definition.AssemblyReferences) { 678 AssemblyDefinition def = assemblyResolver.Resolve (reference); 679 nodes = ContractNodes.GetContractNodes (new AssemblyNode (def), (s) => { }); 680 if (nodes != null) 681 break; 682 } 683 } 684 685 if (nodes == null) 686 return false; 687 688 var extractor = new ContractExtractor (nodes, assembly, true); 689 assembly = (AssemblyNode) extractor.Visit (assembly); 690 return true; 691 } 692 } 693 } 694