Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,234 @@
//
// ContractExtractor.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.AST.Visitors;
namespace Mono.CodeContracts.Static.ContractExtraction {
class ContractExtractor : DefaultNodeVisitor {
private readonly AssemblyNode assembly;
private readonly ContractNodes contract_nodes;
private readonly bool verbose;
private readonly Dictionary<Method, Method> visited_methods;
public ContractExtractor (ContractNodes contractNodes, AssemblyNode assembly)
: this (contractNodes, assembly, DebugOptions.Debug)
{
}
public ContractExtractor (ContractNodes contractNodes, AssemblyNode assembly, bool verbose)
{
this.visited_methods = new Dictionary<Method, Method> ();
this.contract_nodes = contractNodes;
this.assembly = assembly;
this.verbose = verbose;
}
public override AssemblyNode VisitAssembly (AssemblyNode node)
{
if (node == null)
return null;
if (this.verbose)
Console.WriteLine ("Extracting from '{0}'", this.assembly.FullName);
return base.VisitAssembly (node);
}
public override Method VisitMethod (Method node)
{
if (node == null)
return null;
if (this.visited_methods.ContainsKey (node))
return node;
this.visited_methods.Add (node, node);
node.ContractProvider = ExtractContractsFromMethod;
return node;
}
public void ExtractContractsFromMethod (Method method)
{
MethodContract contract = method.MethodContract = new MethodContract (method);
List<Requires> preconditions = null;
List<Ensures> postconditions = null;
if (method.IsAbstract)
return;
if (method.Body != null && method.Body.Statements != null) {
if (this.verbose)
Console.WriteLine (method.FullName);
ExtractContractsInternal (method, ref preconditions, ref postconditions);
contract.Requires = preconditions;
contract.Ensures = postconditions;
}
}
private void ExtractContractsInternal (Method method, ref List<Requires> preconditions, ref List<Ensures> postconditions)
{
if (method == null)
return;
if (this.verbose)
Console.WriteLine ("Method: " + method.FullName);
Block body = method.Body;
if (body == null || body.Statements == null || body.Statements.Count <= 0)
return;
int lastBlockContainingContract;
int lastStatementContainingContract;
int begin = 0;
bool contractsFound = FindLastBlockWithContracts (body.Statements, begin,
out lastBlockContainingContract, out lastStatementContainingContract);
if (!contractsFound) {
if (this.verbose)
Console.WriteLine ("\tNo contracts found");
return;
}
List<Statement> contractSection = HelperMethods.ExtractContractBlocks (body.Statements, begin, 0,
lastBlockContainingContract, lastStatementContainingContract);
preconditions = new List<Requires> ();
postconditions = new List<Ensures> ();
ExtractPrePostConditionsFromContractSection (contractSection, preconditions, postconditions);
}
private bool ExtractPrePostConditionsFromContractSection (List<Statement> contractSection,
List<Requires> preconditions, List<Ensures> postconditions)
{
List<Statement> blocks = contractSection;
int firstBlockIndex = 0;
int blocksCount = blocks.Count;
int firstStmtIndex = HelperMethods.FindNextRealStatement (((Block) blocks [firstBlockIndex]).Statements, 0);
bool wasEndContractBlock = false;
for (int lastBlockIndex = firstBlockIndex; lastBlockIndex < blocksCount; ++lastBlockIndex) {
var block = (Block) blocks [lastBlockIndex];
if (block == null)
continue;
int cnt = block.Statements == null ? 0 : block.Statements.Count;
for (int lastStmtIndex = 0; lastStmtIndex < cnt; ++lastStmtIndex) {
Statement s = block.Statements [lastStmtIndex];
if (s == null)
continue;
Method calledMethod = HelperMethods.IsMethodCall (s);
if (!this.contract_nodes.IsContractMethod (calledMethod))
continue;
if (wasEndContractBlock) {
if (DebugOptions.Debug)
Console.WriteLine ("Contract call after prior ContractBlock");
break;
}
if (this.contract_nodes.IsEndContractBlock (calledMethod)) {
wasEndContractBlock = true;
continue;
}
//here we definitely know that s is ExpressionStatement of (MethodCall). see HelperMethods.IsMethodCall(s)
var methodCall = ((ExpressionStatement) s).Expression as MethodCall;
Expression assertionExpression = methodCall.Arguments [0];
Expression expression;
if (firstBlockIndex == lastBlockIndex && firstStmtIndex == lastStmtIndex)
expression = assertionExpression;
else {
block.Statements [lastStmtIndex] = new ExpressionStatement (assertionExpression);
List<Statement> contractBlocks = HelperMethods.ExtractContractBlocks (blocks, firstBlockIndex, firstStmtIndex,
lastBlockIndex, lastStmtIndex);
var b = new Block (contractBlocks);
expression = new BlockExpression (b);
}
MethodContractElement methodContractElement = null;
if (this.contract_nodes.IsPlainPrecondition (calledMethod)) {
var requires = new Requires (expression);
methodContractElement = requires;
} else if (this.contract_nodes.IsPostCondition (calledMethod))
methodContractElement = new Ensures (expression);
if (methodContractElement == null)
throw new InvalidOperationException ("Unrecognized contract method");
if (methodCall.Arguments.Count > 1) {
Expression userMessage = methodCall.Arguments [1];
methodContractElement.UserMessage = userMessage;
}
switch (methodContractElement.NodeType) {
case NodeType.Requires:
var requires = (Requires) methodContractElement;
preconditions.Add (requires);
break;
case NodeType.Ensures:
var ensures = (Ensures) methodContractElement;
postconditions.Add (ensures);
break;
}
}
}
return true;
}
private bool FindLastBlockWithContracts (List<Statement> statements, int beginning,
out int lastBlockContainingContract, out int lastStatementContainingContract)
{
lastBlockContainingContract = -1;
lastStatementContainingContract = -1;
for (int i = statements.Count - 1; i >= beginning; i--) {
var block = statements [i] as Block;
if (block == null || block.Statements == null || block.Statements.Count <= 0)
continue;
for (int j = block.Statements.Count - 1; j >= 0; j--) {
if (this.contract_nodes.IsContractCall (block.Statements [j]) == null)
continue;
lastBlockContainingContract = i;
lastStatementContainingContract = j;
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,221 @@
//
// ContractNodes.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Mono.CodeContracts.Static.AST;
namespace Mono.CodeContracts.Static.ContractExtraction {
class ContractNodes {
public static readonly string ContractNamespace = "System.Diagnostics.Contracts";
public static readonly string ContractClassName = "Contract";
public static readonly string RequiresName = "Requires";
public static readonly string EnsuresName = "Ensures";
public static readonly string AssertName = "Assert";
public static readonly string AssumeName = "Assume";
public static readonly string EndContractBlockName = "EndContractBlock";
[RepresentationFor ("Contract.Assert(bool)")]
public readonly Method AssertMethod;
[RepresentationFor ("Contract.Assert(bool, string)")]
public readonly Method AssertWithMessageMethod;
[RepresentationFor ("Contract.Assume(bool)")]
public readonly Method AssumeMethod;
[RepresentationFor ("Contract.Assume(bool, string)")]
public readonly Method AssumeWithMessageMethod;
[RepresentationFor ("System.Diagnostics.Contracts.Contract")]
public readonly Class ContractClass;
[RepresentationFor ("Contract.EndContractBlock()")]
public readonly Method EndContractBlock;
[RepresentationFor ("Contract.Ensures(bool)")]
public readonly Method EnsuresMethod;
[RepresentationFor ("Contract.Ensures(bool, string)")]
public readonly Method EnsuresWithMessageMethod;
[RepresentationFor ("Contract.Requires(bool)")]
public readonly Method RequiresMethod;
[RepresentationFor ("Contract.Requires(bool, string)")]
public readonly Method RequiresWithMessageMethod;
private ContractNodes (AssemblyNode assembly, Action<string> errorHandler)
{
CoreSystemTypes.ModuleDefinition = assembly.Modules.First ().Definition;
if (errorHandler != null)
ErrorFound += errorHandler;
this.ContractClass = assembly.GetType (ContractNamespace, ContractClassName) as Class;
if (this.ContractClass == null)
return;
IEnumerable<Method> methods = this.ContractClass.GetMethods (RequiresName, CoreSystemTypes.Instance.TypeBoolean);
foreach (Method method in methods) {
if (method.GenericParameters == null || method.GenericParameters.Count == 0)
this.RequiresMethod = method;
}
if (this.RequiresMethod == null) {
this.ContractClass = null;
return;
}
methods = this.ContractClass.GetMethods (RequiresName, CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
foreach (Method method in methods) {
if (method.GenericParameters == null || method.GenericParameters.Count == 0)
this.RequiresWithMessageMethod = method;
}
this.EnsuresMethod = this.ContractClass.GetMethod (EnsuresName, CoreSystemTypes.Instance.TypeBoolean);
this.EnsuresWithMessageMethod = this.ContractClass.GetMethod (EnsuresName,
CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
this.AssertMethod = this.ContractClass.GetMethod (AssertName, CoreSystemTypes.Instance.TypeBoolean);
this.AssertWithMessageMethod = this.ContractClass.GetMethod (AssertName,
CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
this.AssumeMethod = this.ContractClass.GetMethod (AssumeName, CoreSystemTypes.Instance.TypeBoolean);
this.AssumeWithMessageMethod = this.ContractClass.GetMethod (AssumeName,
CoreSystemTypes.Instance.TypeBoolean, CoreSystemTypes.Instance.TypeString);
this.EndContractBlock = this.ContractClass.GetMethod (EndContractBlockName);
foreach (FieldInfo fieldInfo in typeof (ContractNodes).GetFields ()) {
if (fieldInfo.GetValue (this) != null)
continue;
string runtimeName = null;
bool isRequired = false;
object[] attributes = fieldInfo.GetCustomAttributes (typeof (RepresentationForAttribute), false);
foreach (object attribute in attributes) {
var representationForAttribute = attribute as RepresentationForAttribute;
if (representationForAttribute != null) {
runtimeName = representationForAttribute.RuntimeName;
isRequired = representationForAttribute.IsRequired;
break;
}
}
if (isRequired) {
string message = string.Format ("Could not find contract node for '{0}'", fieldInfo.Name);
if (runtimeName != null)
message = string.Format ("Could not find the method/type '{0}'", runtimeName);
FireErrorFound (message);
ClearFields ();
}
}
}
public static ContractNodes GetContractNodes (AssemblyNode assembly, Action<string> errorHandler)
{
var contractNodes = new ContractNodes (assembly, errorHandler);
if (contractNodes.ContractClass != null)
return contractNodes;
return null;
}
private void ClearFields ()
{
foreach (FieldInfo fieldInfo in typeof (ContractNodes).GetFields ()) {
object[] customAttributes = fieldInfo.GetCustomAttributes (typeof (RepresentationForAttribute), false);
if (customAttributes.Length == 1)
fieldInfo.SetValue (this, null);
}
}
public event Action<string> ErrorFound;
private void FireErrorFound (string message)
{
if (ErrorFound == null)
throw new InvalidOperationException (message);
ErrorFound (message);
}
public Method IsContractCall (Statement s)
{
Method m = HelperMethods.IsMethodCall (s);
if (IsContractMethod (m))
return m;
return null;
}
public bool IsContractMethod (Method method)
{
if (method == null)
return false;
if (IsPlainPrecondition (method) || IsPostCondition (method) || IsEndContractBlock (method))
return true;
return false;
}
public bool IsPostCondition (Method method)
{
TypeNode genericArgument;
return IsContractMethod (EnsuresName, method, out genericArgument) && genericArgument == null;
}
public bool IsPlainPrecondition (Method method)
{
TypeNode genericArgument;
return IsContractMethod (RequiresName, method, out genericArgument);
}
private bool IsContractMethod (string methodName, Method m, out TypeNode genericArgument)
{
genericArgument = null;
if (m == null)
return false;
if (m.HasGenericParameters) {
if (m.GenericParameters == null || m.GenericParameters.Count != 1)
return false;
genericArgument = m.GenericParameters [0];
}
return m.Name != null && m.Name == methodName &&
(m.DeclaringType.Equals (this.ContractClass)
|| (m.Parameters != null && m.Parameters.Count == 3 && m.DeclaringType != null && m.DeclaringType.Name != ContractClassName));
}
public bool IsEndContractBlock (Method method)
{
TypeNode dummy;
return IsContractMethod (EndContractBlockName, method, out dummy);
}
}
}

View File

@@ -0,0 +1,91 @@
//
// GatherLocals.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using Mono.CodeContracts.Static.AST;
using Mono.CodeContracts.Static.AST.Visitors;
namespace Mono.CodeContracts.Static.ContractExtraction {
class GatherLocals : NodeInspector {
public HashSet<Local> Locals = new HashSet<Local> ();
private Local exempt_result_local;
public override void VisitLocal (Local node)
{
if (!IsLocalExempt (node) && !this.Locals.Contains (node))
this.Locals.Add (node);
base.VisitLocal (node);
}
public override void VisitAssignmentStatement (AssignmentStatement node)
{
if (node.Target is Local && IsResultExpression (node.Source))
this.exempt_result_local = (Local) node.Target;
base.VisitAssignmentStatement (node);
}
private bool IsResultExpression (Expression expression)
{
var methodCall = expression as MethodCall;
if (methodCall == null)
return false;
var memberBinding = methodCall.Callee as MemberBinding;
if (memberBinding == null)
return false;
var method = memberBinding.BoundMember as Method;
if (method == null)
return false;
return method.HasGenericParameters && method.Name == "Result" && method.DeclaringType != null && method.DeclaringType.Name == "Contract";
}
private bool IsLocalExempt (Local local)
{
if (local == this.exempt_result_local)
return true;
bool result = false;
if (local.Name != null && !local.Name.StartsWith ("local"))
result = true;
TypeNode type = local.Type;
if (type == null || HelperMethods.IsCompilerGenerated (type) || local.Name == "_preconditionHolds")
return true;
if (result)
return LocalNameIsExempt (local.Name);
return true;
}
private bool LocalNameIsExempt (string name)
{
return name.StartsWith ("CS$") || name.StartsWith ("VB$");
}
}
}

View File

@@ -0,0 +1,332 @@
//
// HelperMethods.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using Mono.CodeContracts.Static.AST;
namespace Mono.CodeContracts.Static.ContractExtraction {
static class HelperMethods {
public static Method IsMethodCall (Statement s)
{
if (s == null)
return null;
var expressionStatement = s as ExpressionStatement;
if (expressionStatement == null)
return null;
var methodCall = expressionStatement.Expression as MethodCall;
if (methodCall == null)
return null;
var binding = methodCall.Callee as MemberBinding;
if (binding == null)
return null;
return binding.BoundMember as Method;
}
public static Local ExtractPreamble (Method method, ContractNodes contractNodes, Block contractInitializer, out Block postPreamble)
{
postPreamble = null;
return null;
}
public static List<Statement> ExtractContractBlocks (List<Statement> blocks, int firstBlockIndex, int firstStmtIndex, int lastBlockIndex, int lastStmtIndex)
{
var result = new List<Statement> ();
var firstBlock = (Block) blocks [firstBlockIndex];
var block = new Block (new List<Statement> ());
if (firstBlock != null) {
int cnt = firstBlockIndex == lastBlockIndex ? lastStmtIndex + 1 : firstBlock.Statements.Count;
for (int i = firstStmtIndex; i < cnt; i++) {
Statement stmt = firstBlock.Statements [i];
block.Statements.Add (stmt);
if (stmt != null)
firstBlock.Statements [i] = null;
}
}
result.Add (block);
int nextIndex = firstBlockIndex + 1;
if (nextIndex > lastBlockIndex)
return result;
Block newLastBlock = null;
int lastFullBlockIndex = lastBlockIndex - 1;
var lastBlock = (Block) blocks [lastBlockIndex];
if (lastBlock != null && lastStmtIndex == lastBlock.Statements.Count - 1)
lastFullBlockIndex = lastBlockIndex;
else {
newLastBlock = new Block (new List<Statement> ());
if (block.Statements != null && block.Statements.Count > 0) {
var branch = block.Statements [block.Statements.Count - 1] as Branch;
if (branch != null && branch.Target != null && branch.Target == lastBlock)
branch.Target = newLastBlock;
}
}
for (; nextIndex < lastFullBlockIndex; ++nextIndex) {
var curBlock = (Block) blocks [nextIndex];
result.Add (curBlock);
if (curBlock != null) {
blocks [nextIndex] = null;
if (newLastBlock != null && curBlock.Statements != null && curBlock.Statements.Count > 0) {
var branch = curBlock.Statements [curBlock.Statements.Count - 1] as Branch;
if (branch != null && branch.Target != null && branch.Target == lastBlock)
branch.Target = newLastBlock;
}
}
}
if (newLastBlock != null) {
for (int i = 0; i < lastStmtIndex + 1; i++) {
newLastBlock.Statements.Add (lastBlock.Statements [i]);
lastBlock.Statements [i] = null;
}
result.Add (newLastBlock);
}
return result;
}
public static bool IsCompilerGenerated (TypeNode type)
{
throw new NotImplementedException ();
}
public static int FindNextRealStatement (List<Statement> stmts, int beginIndex)
{
if (stmts == null || stmts.Count <= beginIndex)
return -1;
int index = beginIndex;
while (index < stmts.Count && (stmts [index] == null || stmts [index].NodeType == NodeType.Nop))
++index;
return index;
}
public static bool IsReferenceAsVisibleAs (Member member, Member asThisMember)
{
var type = member as TypeNode;
if (type != null)
return IsTypeAsVisibleAs (type, asThisMember);
var method = member as Method;
Member member1;
if (method != null) {
if (method.HasGenericParameters)
throw new NotImplementedException ();
member1 = method;
} else
member1 = Unspecialize (member);
return IsDefinitionAsVisibleAs (member1, asThisMember);
}
private static bool IsDefinitionAsVisibleAs (this Member member, Member asThisMember)
{
Module memberModule = member.Module;
Module asThisMemberModule = asThisMember.Module;
for (Member mbr = member; mbr != null; mbr = mbr.DeclaringType) {
if (!mbr.IsPublic) {
bool visible = false;
for (Member mbr1 = asThisMember; mbr1 != null; mbr1 = mbr1.DeclaringType) {
if (mbr1.IsAssembly) {
if ((mbr1.IsPrivate || mbr1.IsAssembly) && memberModule == asThisMemberModule)
visible = true;
} else if (mbr1.IsFamily) {
if (mbr.IsPrivate) {
if (IsInsideOf (mbr, mbr1) || IsInsideSubclass (mbr, mbr1.DeclaringType))
visible = true;
} else if (mbr.IsFamily && (mbr.DeclaringType == mbr1.DeclaringType || IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType)))
visible = true;
} else if (mbr1.IsFamilyOrAssembly) {
if (mbr.IsPrivate) {
if (memberModule == asThisMemberModule || IsInsideSubclass (mbr, mbr1.DeclaringType))
visible = true;
} else if (mbr.IsAssembly) {
if (memberModule == asThisMemberModule)
visible = true;
} else if (mbr.IsFamily) {
if (IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType))
visible = true;
} else if (mbr.IsFamilyOrAssembly && memberModule == asThisMemberModule && IsSubclassOf (mbr.DeclaringType, mbr1.DeclaringType))
visible = true;
} else if (mbr1.IsPrivate && mbr.IsPrivate && IsInsideOf (mbr, mbr1.DeclaringType))
visible = true;
}
if (!visible)
return false;
}
}
return true;
}
private static bool IsSubclassOf (this TypeNode thisType, TypeNode thatType)
{
if (thatType == null)
return false;
return thisType.IsAssignableTo (thatType);
}
private static bool IsInsideSubclass (this Member member, Member thatValue)
{
var targetType = thatValue as TypeNode;
if (targetType == null)
return false;
for (TypeNode declaringType = member.DeclaringType; declaringType != null; declaringType = declaringType.DeclaringType) {
if (declaringType.IsAssignableTo (targetType))
return true;
}
return false;
}
private static bool IsInsideOf (this Member thisValue, Member thatValue)
{
var typeNode = thatValue as TypeNode;
if (typeNode == null)
return false;
for (TypeNode declaringType = thisValue.DeclaringType; declaringType != null; declaringType = declaringType.DeclaringType) {
if (declaringType == typeNode)
return true;
}
return false;
}
private static Member Unspecialize (Member member)
{
return member;
}
private static bool IsTypeAsVisibleAs (this TypeNode type, Member asThisMember)
{
if (type == null)
return true;
switch (type.NodeType) {
case NodeType.Reference:
return ((Reference) type).ElementType.IsTypeAsVisibleAs (asThisMember);
default:
if (type.HasGenericParameters)
throw new NotImplementedException ();
return IsDefinitionAsVisibleAs (type, asThisMember);
}
}
public static bool IsVisibleFrom (this TypeNode type, TypeNode from)
{
TypeNode declaringType = type.DeclaringType;
if (declaringType != null) {
if (IsContainedIn (from, declaringType) || IsInheritedFrom (from, type))
return true;
if (type.IsNestedFamily)
return IsInheritedFrom (from, declaringType);
if (type.IsNestedPublic)
return IsVisibleFrom (declaringType, from);
if (type.IsNestedInternal) {
if (IsInheritedFrom (from, declaringType))
return true;
if (declaringType.Module == from.Module)
return IsVisibleFrom (declaringType, from);
return false;
}
if (type.IsNestedFamilyAndAssembly)
return from.Module == declaringType.Module && IsInheritedFrom (from, declaringType);
if ((type.IsAssembly || type.IsNestedAssembly) && declaringType.Module == from.Module)
return IsVisibleFrom (declaringType, from);
return false;
}
return type.Module == from.Module || type.IsPublic;
}
public static bool IsVisibleFrom (this Member member, TypeNode from)
{
var type = member as TypeNode;
if (type != null)
return type.IsVisibleFrom (from);
TypeNode declaringType = member.DeclaringType;
if (from.IsContainedIn (declaringType))
return true;
if (member.IsPublic)
return declaringType.IsVisibleFrom (from);
if (member.IsFamily)
return from.IsInheritedFrom (declaringType);
if (member.IsFamilyAndAssembly)
return from.Module == declaringType.Module && from.IsInheritedFrom (declaringType);
if (member.IsFamilyOrAssembly) {
if (from.IsInheritedFrom (declaringType))
return true;
if (from.Module == declaringType.Module)
return declaringType.IsVisibleFrom (from);
return false;
}
return member.IsAssembly && declaringType.Module == from.Module && declaringType.IsVisibleFrom (from);
}
public static bool IsInheritedFrom (this TypeNode type, TypeNode from)
{
TypeNode baseClass;
if (type.HasBaseClass (out baseClass)) {
if (baseClass == from || baseClass.IsInheritedFrom (from))
return true;
}
return false;
}
private static bool HasBaseClass (this TypeNode type, out TypeNode baseClass)
{
var clazz = type as Class;
if (clazz != null && clazz.BaseType != null) {
baseClass = clazz.BaseType;
return true;
}
baseClass = default(TypeNode);
return false;
}
public static bool IsContainedIn (this TypeNode inner, TypeNode outer)
{
if (inner == outer)
return true;
if (inner.DeclaringType != null)
return inner.DeclaringType.IsContainedIn (outer);
return false;
}
}
}

View File

@@ -0,0 +1,48 @@
//
// RepresentationForAttribute.cs
//
// Authors:
// Alexander Chebaturkin (chebaturkin@gmail.com)
//
// Copyright (C) 2011 Alexander Chebaturkin
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.CodeContracts.Static.ContractExtraction {
[AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
sealed class RepresentationForAttribute : Attribute {
public RepresentationForAttribute (string runtimeName)
: this (runtimeName, true)
{
}
private RepresentationForAttribute (string runtimeName, bool isRequired)
{
RuntimeName = runtimeName;
IsRequired = isRequired;
}
public string RuntimeName { get; private set; }
public bool IsRequired { get; private set; }
}
}