public override Identifier AppendAttributeIfAllowed(Identifier id){ Debug.Assert(id != null); string idText = id.SourceContext.SourceText; if (idText == null || idText.Length == 0 || idText[0] == '@') return null; Identifier result = new Identifier(id.Name+"Attribute", id.SourceContext); result.Prefix = id.Prefix; return result; }
/// <summary> /// Within "node", replace occurrences of identifiers matching oldName (by /// value) with the given newNode. newNode must be an expression. /// </summary> /// <param name="node"></param> /// <param name="oldName"></param> /// <param name="newNode"></param> public static void Replace(Node node, Identifier oldName, Node newNode) { if (!(newNode is Expression)) throw new ArgumentException("Replace: newNode must be an Expression"); Replacer replacer = new Replacer(oldName, newNode); replacer.Visit(node); }
private Expression renameParam(Identifier id) { for (int i = 0; i < V2.Count; i++) { if (id.Name.Equals((string)V2[i])) { id.Name = (string)V1[i]; break; } } return id; }
// used to be private internal Replacer(Identifier oldName, Node newNode) { this.oldName = oldName; this.newNode = newNode; if (newNode is Expression) replaceType = ReplaceType.Identifier; else if (newNode is Block) replaceType = ReplaceType.LabeledStatement; else throw new ArgumentException("Replacer: newNode must be Expression or Block"); }
private CodeInspector(Identifier attributeToFind, ContractNodes contractNodes, TypeNode referencingType, bool skipQuantifiers) { this.foundAttribute = false; this.attributeToFind = attributeToFind; this.contractNodes = contractNodes; this.skipQuantifiers = skipQuantifiers; this.referencingType = new Stack<TypeNode>(); if (referencingType != null) { this.referencingType.Push(referencingType); } }
void AddReadAllGroup(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, ArrayList members, Member mixedMember) { // todo: keep track of which members have been read and report error on duplicates MethodCall read = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()); Local sb = new Local(SystemTypes.StringBuilder); bool isMixed = mixedMember != null; if (isMixed) { statements.Add(new AssignmentStatement(sb, new Construct(new MemberBinding(null, SystemTypes.StringBuilder), new ExpressionList(), SystemTypes.StringBuilder))); } Block whileBody = new Block(new StatementList()); BinaryExpression notEndTag = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("NodeType")) , new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne); BinaryExpression notEOF = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne); While w = new While(new BinaryExpression(notEndTag, notEOF, NodeType.And), whileBody); statements.Add(w); Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String,block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String,block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType,block); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); Block childBlock = whileBody; if (isMixed) { // Append the text node to the current StringBuilder contents. childBlock = new Block(new StatementList()); If ifText = new If(IsTextNode(nodeType), new Block(new StatementList()), childBlock); whileBody.Statements.Add(ifText); ExpressionList args = new ExpressionList(); args.Add(new QualifiedIdentifier(reader, Identifier.For("Value"))); ifText.TrueBlock.Statements.Add(new ExpressionStatement(new MethodCall( new QualifiedIdentifier(sb, Identifier.For("Append")), args))); ifText.TrueBlock.Statements.Add(new ExpressionStatement(read)); // advance to next node } If ifElement = new If(new BinaryExpression(nodeType, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("Element")), NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); childBlock.Statements.Add(ifElement); childBlock = ifElement.TrueBlock; //AddConsoleWrite(statements, new Literal("name=",SystemTypes.String)); //AddConsoleWriteLine(statements, nameLocal); //AddConsoleWrite(statements, new Literal("nodeType=",SystemTypes.String)); //AddConsoleWriteLine(statements, nodeType); foreach (NamedNode childNode in members) { if (!(childNode.Member is Field || childNode.Member is Property)) { AddError(statements, reader, RuntimeError.SerializationOfTypeNotSupported, new Literal(childNode.Member.GetType().FullName, SystemTypes.String)); } else { Expression mb = GetMemberBinding(target, childNode.Member); childBlock = AddReadChild(block, childBlock.Statements, childNode.Name, childNode.TypeNode, mb, reader, result, true, false).FalseBlock; // todo: throw error if child is required. (e.g. NonEmptyIEnumerable...) } } // if it isn't any of the expected elements then throw an error. AddError(childBlock.Statements, reader, RuntimeError.NoSuchMember, new Expression[2]{new Literal(tempChecker.GetTypeName(type),SystemTypes.String), nameLocal}); // If it's not an element then consume it anyway to keep the reader advancing. // Probably a comment or PI or something. ifElement.FalseBlock.Statements.Add(new ExpressionStatement(new MethodCall( new QualifiedIdentifier(reader, Identifier.For("Skip")), new ExpressionList()))); if (isMixed) { statements.Add(new AssignmentStatement(GetMemberBinding(target, mixedMember), new MethodCall(new QualifiedIdentifier(sb, Identifier.For("ToString")), new ExpressionList()))); } statements.Add(new AssignmentStatement(result, Literal.True)); }
void AddReadContentNode(ContentNode n, Block block, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, SchemaValidator validator) { if (n.TypeNode == null) { Debug.Assert(n is SequenceNode); // In the class inheritance case we have two independent left and right children inside // a parent sequence that has no unified type or member. SequenceNode s = (SequenceNode)n; AddReadContentNode(s.LeftChild, block, statements, reader, target, required, result, validator); AddReadContentNode(s.RightChild, block, statements, reader, target, required, result, validator); return; } TypeNode ct = n.TypeNode; Debug.Assert(ct != null); if (n.Member != null && !(n.Member is Method)) { target = GetMemberBinding(target, n.Member); ct = target.Type; } // todo: might be content model AND mixed, in which case we have to pass the MixedMember // to AddReadTuple, AddReadChoice and AddReadStream. if (ct.Template == SystemTypes.GenericBoxed){ ct = Checker.GetCollectionElementType(ct); } if (ct is TupleType) { AddReadTuple(block, ct as TupleType, statements, reader, target, required, result); } else if (ct is TypeUnion) { AddReadChoice(block, ct as TypeUnion, statements, reader, target, required, result); } else if (IsStream(ct)) { AddReadStream(block, ct, statements, reader, target, result); } else if (ct is TypeAlias) { AddReadAlias(block, ct as TypeAlias, statements, reader, target, required, result); } else { Identifier name = Checker.GetDefaultElementName(ct); AddReadRequiredChild(block, statements, name, ct, target, reader, result, required, true, false); } }
//================= reader methods ========================================== void AddReadAttributes(TypeNode type, StatementList statements, Identifier reader, Expression target, SchemaValidator validator) { if (validator.Attributes != null) { Block whileBody = new Block(new StatementList()); Literal trueLit = Literal.True; MethodCall movenext = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToNextAttribute")), new ExpressionList()); BinaryExpression condition = new BinaryExpression(movenext, trueLit, NodeType.Eq); While w = new While(condition, whileBody); statements.Add(w); Block lastElseBlock = null; Local nameLocal = new Local(SystemTypes.String); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); Local nsLocal = new Local(SystemTypes.String); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); foreach (SchemaAttDef ad in validator.Attributes) { // todo: any way to do tokenized compares? BinaryExpression nameEqual = new BinaryExpression(nameLocal, new Literal(ad.Name.Name, SystemTypes.String), NodeType.Eq); BinaryExpression nsEqual = new BinaryExpression(nsLocal, new Literal(ad.Name.Prefix != null ? ad.Name.Prefix.Name : "", SystemTypes.String), NodeType.Eq); Block elseBlock = new Block(new StatementList()); If ifExpr = new If(new BinaryExpression(nameEqual, nsEqual, NodeType.And), new Block(new StatementList()), elseBlock); if (lastElseBlock != null) { lastElseBlock.Statements.Add(ifExpr); } else { whileBody.Statements.Add(ifExpr); } lastElseBlock = elseBlock; // body of if test, parse the attribute value as the specified type. Debug.Assert(ad.Member is Field || ad.Member is Property); AddReadSimpleType(Checker.GetMemberType(ad.Member), ifExpr.TrueBlock.Statements, reader, GetMemberBinding(target, ad.Member), null, true); } //todo: report unknown attributes? } }
void AddWriteChoice(TypeUnion tu, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { // generate the following code: // Type srcType = src.GetType(); // if (choiceType.IsAssignableFrom(srcType)){ // XxxxSerializer s = new XxxxSerializer(); // s.Serialize((runtimeType)src, writer); // } else if (...) { // // and so on. // } // What we cannot do here is by creating nested XmlSerializers // based on runtime type because this could cause infinite recurrsion. // So we cannot serialize a type union where one of the choices is "object". TypeNodeList choices = tu.Types; MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(src, Identifier.For("GetType")); call.Operands = new ExpressionList(); Local local = new Local(SystemTypes.Type); statements.Add(new AssignmentStatement(local, call)); for (int i = 0, n = choices.Length; i < n; i++) { TypeNode choiceType = choices[i]; if (choiceType == null) continue; // type resolution error. // if (choiceType.IsAssignableFrom(srcType)){ BinaryExpression condition = new BinaryExpression( new MethodCall( new QualifiedIdentifier(new UnaryExpression(new MemberBinding(null, choiceType), NodeType.Typeof), Identifier.For("IsAssignableFrom")), new ExpressionList(new Expression[] { local })), Literal.True, NodeType.Eq); Block block = new Block(); block.Statements = new StatementList(); BinaryExpression cast = CastTo(src, choiceType); Expression name = null, ns = null; GetNameAndNamespace(choiceType, out name, out ns); Expression simplename = name, simplens = ns; // Check for choice of type: [string] and match this with XmlTextNode. TypeNode unwrapped = UnwrapSingletonTuple(choiceType, true); if (unwrapped == null) unwrapped = choiceType; if (unwrapped != null && unwrapped.IsPrimitive) { simplename = simplens = null; choiceType = unwrapped; } if (!AddWriteSimpleType(choiceType, block.Statements, referringType, writer, cast, simplename, simplens)) { AddCallSerializer(choiceType, block.Statements, cast, writer, name, ns); } If ifStatement = new If(condition, block, null); statements.Add(ifStatement); } }
void AddWriteMember(Member child, Identifier name, StatementList statements, TypeNode referringType, Expression src, Identifier writer, bool emptyElementOnNull) { src = GetMemberBinding(src, child); TypeNode type = src.Type; if (type == null) return; if (type.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); type = Checker.GetCollectionElementType(type); src = CastTo(src, type);//unbox it } if (child.IsAnonymous) { if (type is TypeAlias) { TypeAlias alias = (TypeAlias)type; src = CastTo(src, alias.AliasedType); //unbox it AddWriteElement(statements, referringType, writer, alias.Name, src, alias.AliasedType, emptyElementOnNull); } else if (!AddWriteSimpleType(type, statements, referringType, writer, src, Literal.Null, Literal.Null)) { if (type is TupleType || type is TypeUnion || IsStream(type)) { AddCallSerializer(type, statements, src, writer, Literal.Null, Literal.Null); } else { AddWriteElement(statements, referringType, writer, type.Name, src, type, emptyElementOnNull); } } } else if (type is TypeAlias) { TypeAlias alias = (TypeAlias)type; src = CastTo(src, alias.AliasedType); //unbox it AddWriteElement(statements, referringType, writer, name, src, alias.AliasedType, emptyElementOnNull); } else { AddWriteElement(statements, referringType, writer, name, src, type, emptyElementOnNull); } }
void AddWriteString(StatementList statements, TypeNode referringType, Identifier writer, Expression src) { statements = AddCheckForNull(statements, Duplicate(src, referringType), SystemTypes.String); statements.Add( new ExpressionStatement( new MethodCall(new QualifiedIdentifier(writer,Identifier.For("WriteString")), new ExpressionList(src)))); }
void AddCallDeserializer(TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result) { Class memberSerializer = this.CreateSerializerFor(type); // call the Deserialize method on it, and assign result to target object. ExpressionList args = new ExpressionList(); args.Add(reader); args.Add(required); if (result is Local) result = new UnaryExpression(result, NodeType.AddressOf); args.Add(result); MethodCall call = new MethodCall(); Method deserialize = memberSerializer.GetMethod(Identifier.For("Deserialize"), new TypeNode[3] { Runtime.XmlSerializationReader, SystemTypes.Boolean, SystemTypes.Boolean.GetReferenceType() } ); call.Callee = new MemberBinding(new MemberBinding(null, memberSerializer), deserialize); call.Operands = args; statements.Add(new AssignmentStatement(target, call)); }
If AddReadChild(Block scope, StatementList statements, Identifier name, TypeNode type, Expression target, Identifier reader, Expression result, bool unwrapChild, bool ignoreNamespace) { ExpressionList args = new ExpressionList(); args.Add(new Literal(name.Name, SystemTypes.String)); if (name.Prefix != null) args.Add(new Literal(name.Prefix.Name, SystemTypes.String)); // see if we're on a text node... Local nodeType = new Local(Identifier.For("nodeType"), Runtime.XmlNodeType, scope); statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); StatementList ifTextStatements = new StatementList(); If ifIsText = new If( new BinaryExpression(IsTextNode(nodeType), new BinaryExpression(nodeType, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Eq), NodeType.Or), new Block(ifTextStatements), new Block(new StatementList())); statements.Add(ifIsText); // then see if we can force the text into the desired type. TypeNode unwrapped = UnwrapSingletonTuple(Unwrap(type), false); if (unwrapped == null) unwrapped = type; Expression readString = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadString")), null, NodeType.Callvirt, SystemTypes.String); Expression coercion = GetConvertFromString(unwrapped, readString, false); if (coercion != null) { ifTextStatements = ifIsText.TrueBlock.Statements; ifTextStatements.Add(new AssignmentStatement(target, CastTo(CastTo(coercion, unwrapped),type))); ifTextStatements.Add(new AssignmentStatement(result, Literal.True)); } statements = ifIsText.FalseBlock.Statements; If ifFound = null; string method = ignoreNamespace ? "IsStartElementIgnoreNamespace" : "IsStartElement"; MethodCall isStartEle = new MethodCall(new QualifiedIdentifier(reader, Identifier.For(method)), args); ifFound = new If(isStartEle, new Block(new StatementList()), new Block(new StatementList())); statements.Add(ifFound); statements = ifFound.TrueBlock.Statements; statements.Add(new AssignmentStatement(result, Literal.True)); // body of if test, parse the child element as the specified type. MethodCall read = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()); bool isStructuralType = this.IsStructuralType(type); if (isStructuralType && unwrapChild) { // consume member element wrapper. statements.Add(new ExpressionStatement(read)); } if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } if (!AddReadSimpleType(type, statements, reader, target, result, false)) { AddCallDeserializer(type, statements, reader, target, result, result); } if (isStructuralType && unwrapChild) { // consume member element end tag wrapper. statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadEndTag")), new ExpressionList(new Literal(name.Name, SystemTypes.String))))); } return ifFound; }
void InvalidContent(StatementList statements, Identifier reader, string expecting) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("InvalidContent")), new ExpressionList(new Expression[1]{ new Literal(expecting, SystemTypes.String)})))); }
void AddError(StatementList statements, Identifier reader, RuntimeError code, params Expression[] args) { ExpressionList list = new ExpressionList(); list.Add(new Literal(code, Runtime.RuntimeError)); foreach (Expression e in args) list.Add(e); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Error")), list))); }
void AddWriteContentNode(ContentNode n, StatementList statements, TypeNode referringType, Identifier writer, Expression source) { if (n.TypeNode == null) { Debug.Assert(n is SequenceNode); // In the class inheritance case we have two independent left and right children inside // a parent sequence that has no unified type or member. SequenceNode s = (SequenceNode)n; AddWriteContentNode(s.LeftChild, statements, referringType, writer, source); AddWriteContentNode(s.RightChild, statements, referringType, writer, source); return; } TypeNode ct = n.TypeNode; Expression src = source; if (n.Member != null && !(n.Member is Method)) { src = GetMemberBinding(source, n.Member, ct); } if (ct.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, referringType), ct); ct = Checker.GetCollectionElementType(ct); src = CastTo(src, ct);//unbox it } if (ct is TupleType) { AddWriteTuple(ct as TupleType, statements, referringType, src, writer); } else if (ct is TypeUnion) { AddWriteChoice(ct as TypeUnion, statements, referringType, src, writer); } else if (IsStream(ct)) { AddWriteStream(ct, statements, referringType, src, writer); } else if (ct is TypeAlias) { TypeAlias alias = (TypeAlias)ct; src = CastTo(src, alias.AliasedType); //unbox it AddWriteElement(statements, referringType, writer, alias.Name, src, alias.AliasedType, true); } else { AddWriteElement(statements, referringType, writer, ct.Name, src, ct, true); } }
void AddWriteElement(StatementList statements, TypeNode referringType, Identifier writer, Identifier name, Expression src, TypeNode mt, bool emptyElementOnNull) { if (mt.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, referringType), mt); mt = Checker.GetCollectionElementType(mt); // check for null and unbox src = CastTo(src, mt); //unbox it } Literal nameLit = new Literal(name.ToString(), SystemTypes.String); Literal nsLit = (name.Prefix != null) ? new Literal(name.Prefix.Name, SystemTypes.String) : Literal.Null; if (!emptyElementOnNull) { statements = AddCheckForNull(statements, Duplicate(src, referringType), mt); } if (!AddWriteSimpleType(mt, statements, referringType, writer, src, nameLit, nsLit)) { AddCallSerializer(mt, statements, src, writer, nameLit, nsLit); } }
bool AddWriteSimpleType(TypeNode simpleType, StatementList statements, TypeNode referringType, Identifier writer, Expression src, Expression name, Expression ns) { Identifier method = null; TypeNode type = Unwrap(simpleType); ExpressionList args = new ExpressionList(src); if (type == SystemTypes.String) { method = Identifier.For("WriteString"); } else if( type == SystemTypes.Boolean) { method = Identifier.For("WriteBoolean"); } else if( type == SystemTypes.Int8) { method = Identifier.For("WriteSByte"); } else if( type == SystemTypes.Char) { method = Identifier.For("WriteChar"); } else if( type == SystemTypes.DateTime) { method = Identifier.For("WriteDateTime"); } else if( type == SystemTypes.Decimal) { method = Identifier.For("WriteDecimal"); } else if( type == SystemTypes.Double) { method = Identifier.For("WriteDouble"); } else if( type == SystemTypes.Guid) { method = Identifier.For("WriteGuid"); } else if( type == SystemTypes.Int16) { method = Identifier.For("WriteInt16"); } else if( type == SystemTypes.Int32) { method = Identifier.For("WriteInt32"); } else if( type == SystemTypes.Int64) { method = Identifier.For("WriteInt64"); } else if( type == SystemTypes.UInt8) { method = Identifier.For("WriteByte"); } else if( type == SystemTypes.Single) { method = Identifier.For("WriteSingle"); } else if( type == SystemTypes.TimeSpan) { method = Identifier.For("WriteTimeSpan"); } else if( type == SystemTypes.UInt16 ) { method = Identifier.For("WriteUInt16"); } else if( type == SystemTypes.UInt32) { method = Identifier.For("WriteUInt32"); } else if( type == SystemTypes.UInt64) { method = Identifier.For("WriteUInt64"); } else { Expression conversion = GetConvertToString(type, src, false); if (conversion != null) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); method = Identifier.For("WriteString"); args = new ExpressionList(conversion); } else { return false; } } if (name != null) { Identifier id = Checker.GetDefaultElementName(type); string defaultName = id.Name; string defaultNamespace = (id.Prefix != null) ? id.Prefix.Name : null; Expression localName = new Local(SystemTypes.String); Expression localNamespace = new Local(SystemTypes.String); Expression safeName = name; if (name is Literal) { if (name == Literal.Null) { localName = new Literal(defaultName, SystemTypes.String); localNamespace = new Literal(defaultNamespace, SystemTypes.String); } else { localName = name; localNamespace = ns; } } else { If nameNull = new If(new BinaryExpression(name, Literal.Null, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); nameNull.TrueBlock.Statements.Add(new AssignmentStatement(localName, new Literal(defaultName, SystemTypes.String))); nameNull.TrueBlock.Statements.Add(new AssignmentStatement(localNamespace, new Literal(defaultNamespace, SystemTypes.String))); nameNull.FalseBlock.Statements.Add(new AssignmentStatement(localName, name)); nameNull.FalseBlock.Statements.Add(new AssignmentStatement(localNamespace, ns)); statements.Add(nameNull); } MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement")); call.Operands = new ExpressionList(); call.Operands.Add(localName); call.Operands.Add(localNamespace); statements.Add( new ExpressionStatement( call ) ); } StatementList notNull = statements; if (!type.IsValueType) { notNull = AddCheckForNull(statements, Duplicate(src, referringType), type); } notNull.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, method), args))); if (name != null) { MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement")); call.Operands = new ExpressionList(); statements.Add( new ExpressionStatement( call ) ); } return true; }
void AddCallSerializer(TypeNode srcType, StatementList statements, Expression src, Identifier writer, Expression rootName, Expression rootNamespace ) { TypeNode type = Unwrap(srcType); Class memberSerializer = this.CreateSerializerFor(type); // call the Serialize method on it, passing the member we're serializing. ExpressionList args = new ExpressionList(); args.Add(src); args.Add(writer); args.Add(rootName); args.Add(rootNamespace); MethodCall call = new MethodCall(); Method serialize = memberSerializer.GetMethod(Identifier.For("Serialize"), new TypeNode[4] { type, Runtime.XmlSerializationWriter, SystemTypes.String, SystemTypes.String} ); call.Callee = new MemberBinding(new MemberBinding(null, memberSerializer), serialize); call.Operands = args; statements.Add( new ExpressionStatement( call ) ); }
Literal GetXmlNameFromId(Identifier id) { if (id.Prefix != null && id.Prefix.UniqueKey == xmlnsuri.UniqueKey) { // this is a special namespace return new Literal("xml:"+id.Name, SystemTypes.String); } return new Literal(id.Name, SystemTypes.String); }
void AddWriteTuple(TupleType tuple, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { TypeNode singleton = UnwrapSingletonTuple(tuple, true); if (singleton != null && singleton == SystemTypes.String) { // special case which looks like mixed content. // happens a lot when XML Schema contains SimpleTypes that extend xsd:string. AddWriteSimpleType(singleton, statements, referringType, writer, src, null, null); } else { for (int i = 0, n = tuple.Members.Length; i < n; i++) { Member child = tuple.Members[i]; if (child is Field) { Field f = (Field)child; if (f.Type == null) continue; // type resolution error. // bugbug - what about [XmlElement] custom attributes? AddWriteMember(f, f.Name, statements, referringType, src, writer, true); } } } }
Literal GetXmlNamespaceFromId(Identifier id) { if (id.Prefix == null ) { return Literal.Null; } else if (id.Prefix.UniqueKey == xmlnsuri.UniqueKey) { // this is a special namespace return Literal.Null; } // Let the XmlTextWriter generate an XML prefix for us. return new Literal(id.Prefix.Name, SystemTypes.String); }
void AddWriteStream(TypeNode type, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { // Generate the following code: // XxxxSerializer s = new XxxxSerializer(); // foreach (Xxxx x in src) { // s.Serialize(x,writer); // } // Where Xxxx is the element type for the given stream type. if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) { type = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type); } else { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); } TypeNode ceType = Checker.GetCollectionElementType(type); //todo: should check that type has an IEnumerator. Identifier loopVariable = Identifier.For("e"); loopVariable.Type = ceType; Block body = new Block(); body.Statements = new StatementList(); Expression name, ns; GetNameAndNamespace(ceType, out name, out ns); // call the Serialize method on it, passing the member we're serializing. if (!AddWriteSimpleType(ceType, body.Statements, referringType, writer, loopVariable, name, ns)) { AddCallSerializer(ceType, body.Statements, loopVariable, writer, name, ns); } ForEach fe = new ForEach(ceType, loopVariable, src, body); statements.Add(fe); }
bool AddWriteSimpleAttribute(TypeNode type, Identifier name, StatementList statements, TypeNode referringType, Identifier writer, Expression src) { ExpressionList args = new ExpressionList(); args.Add(GetXmlNameFromId(name)); args.Add(GetXmlNamespaceFromId(name)); args.Add(src); if (type == SystemTypes.String) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeString")), args))); } else if( type == SystemTypes.Boolean) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeBoolean")), args))); } else if( type == SystemTypes.Int8) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeSByte")), args))); } else if( type == SystemTypes.Char) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeChar")), args))); } else if( type == SystemTypes.DateTime) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeDateTime")), args))); } else if( type == SystemTypes.Decimal) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeDecimal")), args))); } else if( type == SystemTypes.Double) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeDouble")), args))); } else if( type == SystemTypes.Guid) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeGuid")), args))); } else if( type == SystemTypes.Int16) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeInt16")), args))); } else if( type == SystemTypes.Int32) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeInt32")), args))); } else if( type == SystemTypes.Int64) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeInt64")), args))); } else if( type == SystemTypes.UInt8) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeByte")), args))); } else if( type == SystemTypes.Single) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeSingle")), args))); } else if( type == SystemTypes.TimeSpan) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeTimeSpan")), args))); } else if( type == SystemTypes.UInt16 ) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeUInt16")), args))); } else if( type == SystemTypes.UInt32) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeUInt32")), args))); } else if( type == SystemTypes.UInt64) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeUInt64")), args))); } else { Expression conversion = GetConvertToString(type, src, true); if (conversion != null) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); ExpressionList args2 = new ExpressionList(); args2.Add(args[0]); args2.Add(args[1]); args2.Add(conversion); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeString")), args2))); } else { return false; } } return true; }
void AddReadContent(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, SchemaValidator validator) { // position us in the content. statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()))); Local elementName = new Local(Identifier.Empty,SystemTypes.String); statements.Add(new AssignmentStatement(elementName, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); // make sure the element is not empty. If isEmpty = AddEmptyElementCheck(statements, reader); // Read the contents. statements = isEmpty.FalseBlock.Statements; statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()))); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()))); ValidationState context = new ValidationState(); context.ErrorHandler = this.errorHandler; validator.validator.InitValidation(context); ArrayList members = null; if (validator.validator is AllElementsContentValidator) { members = validator.validator.ExpectedElements(context, false, false); AddReadAllGroup(serializer, block, type, statements, reader, target, required, result, members, validator.validator.MixedMember); } else { // There should be one root level anonymous Item0 member. SequenceNode seq = (SequenceNode)validator.RootNode; // this is a wrapper node. if (seq == null) { // perhaps it is ContentType.Empty or Mixed. if (validator.validator.ContentType == XmlSchemaContentType.Mixed || validator.validator.ContentType == XmlSchemaContentType.TextOnly){ Debug.Assert(validator.validator.MixedMember != null); statements.Add(new AssignmentStatement(GetMemberBinding(target, validator.validator.MixedMember), new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadStringElement")), new ExpressionList()))); } return; } else { ContentNode n = seq.LeftChild; AddReadContentNode(n, block, statements, reader, target, required, result, validator); } } // consume final end tag statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadEndTag")), new ExpressionList(elementName)))); }
bool AddReadSimpleType(TypeNode simpleType, StatementList statements, Identifier reader, Expression mb, Expression result, bool always) { TypeNode type = Unwrap(simpleType); string method = null; Expression conversion = null; if (type == SystemTypes.String) { method = "ReadStringElement"; } else if (type == SystemTypes.Boolean) { method = "ReadBool"; } else if (type == SystemTypes.Int8) { method = "ReadSByte"; } else if (type == SystemTypes.Char) { method = "ReadChar"; } else if (type == SystemTypes.DateTime) { method = "ReadDateTime"; } else if (type == SystemTypes.Decimal) { method = "ReadDecimal"; } else if (type == SystemTypes.Double) { method = "ReadDouble"; } else if (type == SystemTypes.Guid) { method = "ReadGuid"; } else if (type == SystemTypes.Int16) { method = "ReadInt16"; } else if (type == SystemTypes.Int32) { method = "ReadInt32"; } else if (type == SystemTypes.Int64) { method = "ReadInt64"; } else if (type == SystemTypes.UInt8) { method = "ReadInt8"; } else if (type == SystemTypes.Single) { method = "ReadSingle"; } else if (type == SystemTypes.TimeSpan) { method = "ReadTimeSpan"; } else if (type == SystemTypes.UInt16) { method = "ReadUInt16"; } else if (type == SystemTypes.UInt32) { method = "ReadUInt32"; } else if (type == SystemTypes.UInt64) { method = "ReadUInt64"; } else { // see if there's a type converter for it. conversion = GetConvertFromString(type, new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadStringElement")), null), always); } if (method != null) { conversion = new MethodCall(new QualifiedIdentifier(reader, Identifier.For(method)), null, NodeType.Callvirt, type); } if (conversion == null) return false; // there is no simple conversion! statements.Add(new AssignmentStatement(mb, CastTo(conversion, simpleType))); if (result != null) statements.Add(new AssignmentStatement(result, Literal.True)); return true; }
If AddEmptyElementCheck(StatementList statements, Identifier reader) { // make sure the element is not empty. If isEmpty = new If(new BinaryExpression(new QualifiedIdentifier(reader, Identifier.For("IsEmptyElement")), Literal.True, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); statements.Add(isEmpty); statements = isEmpty.TrueBlock.Statements; // consume empty start tag and just return. statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()))); return isEmpty; }
void AddWriteAttributes(StatementList statements, TypeNode referringType, Identifier writer, Expression source, SchemaValidator validator) { if (validator.Attributes != null) { foreach (SchemaAttDef ad in validator.Attributes) { Identifier name = ad.Name; Expression src = GetMemberBinding(source, ad.Member); if (src.Type == null) continue; // type resolution error. if (!AddWriteSimpleAttribute(src.Type, name, statements, referringType, writer, src)) { // throw exception, attribute has complex type! } } } }
public override Expression VisitIdentifier(Identifier identifier) { Write(identifier.Name); return identifier; }
void AddWriteContent(TypeNode type, StatementList statements, TypeNode referringType, Identifier writer, Expression source, SchemaValidator validator) { if (validator.validator is AllElementsContentValidator) { ValidationState context = new ValidationState(); context.ErrorHandler = this.errorHandler; validator.validator.InitValidation(context); ArrayList members = validator.validator.ExpectedElements(context, false, false); foreach (NamedNode childNode in members) { if (childNode.TypeNode == null) continue; // type resolution error. Expression src = GetMemberBinding(source, childNode.Member, childNode.TypeNode); AddWriteElement(statements, referringType, writer, childNode.Name, src, childNode.TypeNode, false); } } else { // Note: there is a SequenceNode wrapper we need to remove and throw away. SequenceNode seq = validator.RootNode as SequenceNode; if (seq != null) { // if seq is null then it's ContentType.Empty or Mixed and mixed is handled at the end. ContentNode n = seq.LeftChild; AddWriteContentNode(n, statements, referringType, writer, source); } } Member mixed = validator.validator.MixedMember; if (mixed != null) { MemberBinding mb = GetMemberBinding(source, mixed); if (mb.Type != null) AddWriteString(statements, referringType, writer, mb); } }