// Looks for contract attributes in a list and creates statements that // should be inserted at the beginning of the method that those attributes // are a part of. `variableName` is the name of the associated method // argument, or null if the attributes are attached to the return value or // the entire method. Returns the attribute list with contract attributes // removed. internal VList <LNode> Process(VList <LNode> attributes, LNode variableName, bool isPropSetter = false) { return(attributes.SmartWhere(attr => { LNode exceptionType = null; var mode = GetContractAttrMode(attr, out exceptionType); if (mode != null) { ProcessAttribute(attr, mode, exceptionType, variableName, isPropSetter); return false; // Remove contract attribute from method signature } return true; // No change })); }
LNode MaybeQuoteList(VList <LNode> list, bool isAttributes = false) { if (isAttributes && _ignoreTrivia) { list = list.SmartWhere(n => !n.IsTrivia || n.IsIdNamed(S.TriviaInParens)); } if (list.IsEmpty) { return(null); } else if (_doSubstitutions && list.Any(a => VarArgExpr(a) != null)) { if (list.Count == 1) { return(F.Call(LNode_List, VarArgExpr(list[0]))); } // If you write something like quote(Foo($x, $(...y), $z)), a special // output style is used to accommodate the variable argument list. LNode argList = F.Call(LNode_List); foreach (LNode arg in list) { var vae = VarArgExpr(arg); if (vae != null) { argList = F.Call(F.Dot(argList, F.Id("AddRange")), vae); } else { argList = F.Call(F.Dot(argList, F.Id("Add")), QuoteOne(arg)); } } return(argList); } else { return(F.Call(LNode_List, list.SmartSelect(item => QuoteOne(item)))); } }
public static LNode ContractsOnProperty(LNode prop, IMacroContext context) { // Performance note: one should keep in mind that this macro usually // has no effect. It looks for contracts and usually finds none. LNode oldProp = prop; if (prop.ArgCount == 4) { LNode braces = prop[3]; var oldBraces = braces; var rw = new CodeContractRewriter(prop.Args[0], prop.Args[1], context); // If this has an argument list (this[...]), process its contract attributes prop = ProcessArgContractAttributes(prop, 2, rw); // Remove contract attributes from the property and store in a list VList <LNode> cAttrs = LNode.List(); prop = prop.WithArgChanged(0, GrabContractAttrs(prop.Args[0], ref cAttrs, ContractAppliesTo.Getter)); prop = GrabContractAttrs(prop, ref cAttrs); // Find the getter and setter LNode getter = null, setter = null; int getterIndex = -1, setterIndex = -1; VList <LNode> getterAttrs = LNode.List(), setterAttrs = LNode.List(); bool isLambdaProperty = !braces.Calls(S.Braces); if (isLambdaProperty) { if (cAttrs.Count == 0) { return(null); // lambda property has no contract attributes } // Transform into a normal property getterAttrs = cAttrs; getter = LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(braces)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special); braces = LNode.Call(CodeSymbols.Braces, LNode.List(getter)).SetStyle(NodeStyle.Statement); getterIndex = 0; } else { for (int i = 0; i < braces.Args.Count; i++) { var part = braces.Args[i]; if (part.Calls(S.get)) { getter = part; getterIndex = i; } if (part.Calls(S.set)) { setter = part; setterIndex = i; } } // Now create separate lists of contract attributes for the getter and the setter if (cAttrs.Count != 0) { getterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Getter) != 0); setterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Setter) != 0); } } // Process the discovered attributes to produce prepended statements var sharedPrependStmts = rw.PrependStmts; if (getter != null) { getter = GrabContractAttrs(getter, ref getterAttrs); rw.Process(getterAttrs, null); rw.PrependStmtsToGetterOrSetter(ref braces, getterIndex, getter); } if (setter != null) { rw.PrependStmts = sharedPrependStmts; setter = GrabContractAttrs(setter, ref setterAttrs); rw.Process(setterAttrs, LNode.Id(CodeSymbols.value), true); rw.PrependStmtsToGetterOrSetter(ref braces, setterIndex, setter); } // Update the property if (braces == oldBraces) { return(null); // this is the common case } else { return(prop.WithArgChanged(3, braces)); } } return(null); }
public static LNode ContractsOnProperty(LNode prop, IMacroContext context) { LNode oldProp = prop; if (prop.ArgCount == 4) { LNode braces = prop[3]; var oldBraces = braces; var rw = new CodeContractRewriter(prop.Args[0], prop.Args[1], context); prop = ProcessArgContractAttributes(prop, 2, rw); VList <LNode> cAttrs = LNode.List(); prop = prop.WithArgChanged(0, GrabContractAttrs(prop.Args[0], ref cAttrs, ContractAppliesTo.Getter)); prop = GrabContractAttrs(prop, ref cAttrs); LNode getter = null, setter = null; int getterIndex = -1, setterIndex = -1; VList <LNode> getterAttrs = LNode.List(), setterAttrs = LNode.List(); bool isLambdaProperty = !braces.Calls(S.Braces); if (isLambdaProperty) { if (cAttrs.Count == 0) { return(null); } getterAttrs = cAttrs; getter = LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(braces)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special); braces = LNode.Call(CodeSymbols.Braces, LNode.List(getter)).SetStyle(NodeStyle.Statement); getterIndex = 0; } else { for (int i = 0; i < braces.Args.Count; i++) { var part = braces.Args[i]; if (part.Calls(S.get)) { getter = part; getterIndex = i; } if (part.Calls(S.set)) { setter = part; setterIndex = i; } } if (cAttrs.Count != 0) { getterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Getter) != 0); setterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Setter) != 0); } } var sharedPrependStmts = rw.PrependStmts; if (getter != null) { getter = GrabContractAttrs(getter, ref getterAttrs); rw.Process(getterAttrs, null); rw.PrependStmtsToGetterOrSetter(ref braces, getterIndex, getter); } if (setter != null) { rw.PrependStmts = sharedPrependStmts; setter = GrabContractAttrs(setter, ref setterAttrs); rw.Process(setterAttrs, LNode.Id(CodeSymbols.value), true); rw.PrependStmtsToGetterOrSetter(ref braces, setterIndex, setter); } if (braces == oldBraces) { return(null); } else { return(prop.WithArgChanged(3, braces)); } } return(null); }