/// <summary> /// Write unsupported generic types syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> /// <returns>True if unsupported, false if it is supported</returns> protected virtual bool IsUnsupportedGeneric(XPathNavigator reflection, SyntaxWriter writer) { bool isGeneric = (bool)reflection.Evaluate(apiIsGenericExpression); if(isGeneric) writer.WriteMessage("UnsupportedGeneric_" + this.Language); return isGeneric; }
/// <summary> /// Write attached property syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteAttachedPropertySyntax(XPathNavigator reflection, SyntaxWriter writer) { string getterId = (string)reflection.Evaluate(attachedPropertyGetterExpression); string setterId = (string)reflection.Evaluate(attachedPropertySetterExpression); if(!string.IsNullOrEmpty(getterId)) { writer.WriteString("See "); writer.WriteReferenceLink(getterId); } if(!string.IsNullOrEmpty(setterId)) { if(!string.IsNullOrEmpty(getterId)) writer.WriteString(", "); writer.WriteReferenceLink(setterId); } }
/// <summary> /// Write unsupported variable arguments syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> /// <returns>True if unsupported, false if it is supported</returns> protected virtual bool IsUnsupportedVarargs(XPathNavigator reflection, SyntaxWriter writer) { bool isVarargs = (bool)reflection.Evaluate(apiIsVarargsExpression); if(isVarargs) writer.WriteMessage("UnsupportedVarargs_" + this.Language); return isVarargs; }
/// <summary> /// Write member syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteMemberSyntax(XPathNavigator reflection, SyntaxWriter writer) { string subgroup = (string)reflection.Evaluate(apiSubgroupExpression); string subsubgroup = (string)reflection.Evaluate(apiSubsubgroupExpression); switch(subgroup) { case "constructor": WriteConstructorSyntax(reflection, writer); break; case "method": WriteMethodSyntax(reflection, writer); break; case "property": if(subsubgroup == "attachedProperty") WriteAttachedPropertySyntax(reflection, writer); else WritePropertySyntax(reflection, writer); break; case "event": if(subsubgroup == "attachedEvent") WriteAttachedEventSyntax(reflection, writer); else WriteEventSyntax(reflection, writer); break; case "field": WriteFieldSyntax(reflection, writer); break; } }
/// <summary> /// Write normal method syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteNormalMethodSyntax(XPathNavigator reflection, SyntaxWriter writer) { }
/// <summary> /// Write property syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public abstract void WritePropertySyntax(XPathNavigator reflection, SyntaxWriter writer);
// Methods to write syntax for different kinds of APIs /// <summary> /// This is the main syntax writing method /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public override void WriteSyntax(XPathNavigator reflection, SyntaxWriter writer) { writer.WriteStartBlock(this.Language, this.StyleId); string group = (string)reflection.Evaluate(apiGroupExpression); switch(group) { case "namespace": WriteNamespaceSyntax(reflection, writer); break; case "type": WriteTypeSyntax(reflection, writer); break; case "member": WriteMemberSyntax(reflection, writer); break; } writer.WriteEndBlock(); }
/// <summary> /// Write cast syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteCastSyntax(XPathNavigator reflection, SyntaxWriter writer) { }
/// <summary> /// Write out a type reference /// </summary> /// <param name="reference">The type reference to output</param> /// <param name="writer">The syntax writer to which the type reference is written</param> protected virtual void WriteTypeReference(XPathNavigator reference, SyntaxWriter writer) { switch (reference.LocalName) { case "arrayOf": int rank = Convert.ToInt32(reference.GetAttribute("rank", String.Empty), CultureInfo.InvariantCulture); XPathNavigator element = reference.SelectSingleNode(typeExpression); WriteTypeReference(element, writer); writer.WriteString("["); for (int i = 1; i < rank; i++) { writer.WriteString(","); } writer.WriteString("]"); break; case "pointerTo": XPathNavigator pointee = reference.SelectSingleNode(typeExpression); WriteTypeReference(pointee, writer); writer.WriteString("*"); break; case "referenceTo": XPathNavigator referee = reference.SelectSingleNode(typeExpression); WriteTypeReference(referee, writer); break; case "type": string id = reference.GetAttribute("api", String.Empty); XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression); // !EFW - Support value tuple syntax if (id.StartsWith("T:System.ValueTuple`", StringComparison.Ordinal)) { writer.WriteString("("); while (typeModifiers.MoveNext()) { XPathNodeIterator args = typeModifiers.Current.Select(specializationArgumentsExpression); while (args.MoveNext()) { if (args.CurrentPosition > 1) { writer.WriteString(", "); } WriteTypeReference(args.Current, writer); var elementName = args.Current.GetAttribute("elementName", String.Empty); if (elementName != null) { writer.WriteString(" "); writer.WriteString(elementName); } } } writer.WriteString(")"); } else { WriteNormalTypeReference(id, writer); while (typeModifiers.MoveNext()) { WriteTypeReference(typeModifiers.Current, writer); } } break; case "template": string name = reference.GetAttribute("name", String.Empty); writer.WriteString(name); XPathNodeIterator modifiers = reference.Select(typeModifiersExpression); while (modifiers.MoveNext()) { WriteTypeReference(modifiers.Current, writer); } break; case "specialization": writer.WriteString("<"); XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression); while (arguments.MoveNext()) { if (arguments.CurrentPosition > 1) { writer.WriteString(", "); } WriteTypeReference(arguments.Current, writer); } writer.WriteString(">"); break; } }
/// <summary> /// Write event syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public abstract void WriteEventSyntax(XPathNavigator reflection, SyntaxWriter writer);
/// <summary> /// Write constructor syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public abstract void WriteConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer);
/// <summary> /// Write enumeration syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public abstract void WriteEnumerationSyntax(XPathNavigator reflection, SyntaxWriter writer);
/// <summary> /// This is used to write a string followed by an optional line break if needed (the writer position is /// past the maximum position afterwards). /// </summary> /// <param name="writer">The syntax writer to use</param> /// <param name="text">An optional text string to write before the new line</param> /// <param name="indent">An optional indent to write after the line break</param> /// <returns>True if a new line was written, false if not</returns> public static bool WriteWithLineBreakIfNeeded(SyntaxWriter writer, string text, string indent) { if(!String.IsNullOrEmpty(text)) writer.WriteString(text); if(writer.Position > MaxPosition) { writer.WriteLine(); if(!String.IsNullOrEmpty(indent)) writer.WriteString(indent); return true; } return false; }
/// <summary> /// Write out a normal type reference /// </summary> /// <param name="api">The type reference to output</param> /// <param name="writer">The syntax writer to which the type reference is written</param> protected virtual void WriteNormalTypeReference(string api, SyntaxWriter writer) { switch (api) { case "T:System.Void": writer.WriteReferenceLink(api, "void"); break; case "T:System.String": writer.WriteReferenceLink(api, "string"); break; case "T:System.Boolean": writer.WriteReferenceLink(api, "bool"); break; case "T:System.Byte": writer.WriteReferenceLink(api, "byte"); break; case "T:System.SByte": writer.WriteReferenceLink(api, "sbyte"); break; case "T:System.Char": writer.WriteReferenceLink(api, "char"); break; case "T:System.Int16": writer.WriteReferenceLink(api, "short"); break; case "T:System.Int32": writer.WriteReferenceLink(api, "int"); break; case "T:System.Int64": writer.WriteReferenceLink(api, "long"); break; case "T:System.UInt16": writer.WriteReferenceLink(api, "ushort"); break; case "T:System.UInt32": writer.WriteReferenceLink(api, "uint"); break; case "T:System.UInt64": writer.WriteReferenceLink(api, "ulong"); break; case "T:System.Single": writer.WriteReferenceLink(api, "float"); break; case "T:System.Double": writer.WriteReferenceLink(api, "double"); break; case "T:System.Decimal": writer.WriteReferenceLink(api, "decimal"); break; default: writer.WriteReferenceLink(api); break; } }
/// <summary> /// Write delegate syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public abstract void WriteDelegateSyntax(XPathNavigator reflection, SyntaxWriter writer);
/// <summary> /// Write out a constant's value /// </summary> /// <param name="parent">The parent node</param> /// <param name="writer">The syntax writer</param> protected virtual void WriteConstantValue(XPathNavigator parent, SyntaxWriter writer) { XPathNavigator type = parent.SelectSingleNode(returnsTypeExpression); XPathNavigator value = parent.SelectSingleNode(returnsValueExpression); switch (value.LocalName) { case "nullValue": writer.WriteKeyword("null"); break; case "enumValue": XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element); while (fields.MoveNext()) { string name = fields.Current.GetAttribute("name", String.Empty); if (fields.CurrentPosition > 1) { writer.WriteString("|"); } this.WriteTypeReference(type, writer); writer.WriteString("."); writer.WriteString(name); } break; case "value": string text = value.Value; string typeId = type.GetAttribute("api", String.Empty); switch (typeId) { case "T:System.String": writer.WriteString("\""); writer.WriteString(text); writer.WriteString("\""); break; case "T:System.Boolean": writer.WriteKeyword(Convert.ToBoolean(text, CultureInfo.InvariantCulture) ? "true" : "false"); break; case "T:System.Char": writer.WriteString("'"); writer.WriteString(text); writer.WriteString("'"); break; // Decimal constants get converted to static read-only fields so no need to handle them here case "T:System.Byte": case "T:System.Double": case "T:System.SByte": case "T:System.Int16": case "T:System.Int64": case "T:System.Int32": case "T:System.UInt16": case "T:System.UInt32": case "T:System.UInt64": writer.WriteString(text); break; case "T:System.Single": writer.WriteString(text); writer.WriteString("f"); break; default: // If not a recognized type, just write out the value so that something shows writer.WriteString(text); break; } break; } }
/// <summary> /// Write out a type reference /// </summary> /// <param name="reference">The type reference to output</param> /// <param name="writer">The syntax writer to which the type reference is written</param> protected virtual void WriteTypeReference(XPathNavigator reference, SyntaxWriter writer) { switch(reference.LocalName) { case "arrayOf": int rank = Convert.ToInt32(reference.GetAttribute("rank", String.Empty), CultureInfo.InvariantCulture); XPathNavigator element = reference.SelectSingleNode(typeExpression); WriteTypeReference(element, writer); writer.WriteString("["); for(int i = 1; i < rank; i++) writer.WriteString(","); writer.WriteString("]"); break; case "pointerTo": XPathNavigator pointee = reference.SelectSingleNode(typeExpression); WriteTypeReference(pointee, writer); writer.WriteString("*"); break; case "referenceTo": XPathNavigator referee = reference.SelectSingleNode(typeExpression); WriteTypeReference(referee, writer); break; case "type": string id = reference.GetAttribute("api", String.Empty); WriteNormalTypeReference(id, writer); XPathNodeIterator typeModifiers = reference.Select(typeModifiersExpression); while(typeModifiers.MoveNext()) WriteTypeReference(typeModifiers.Current, writer); break; case "template": string name = reference.GetAttribute("name", String.Empty); writer.WriteString(name); XPathNodeIterator modifiers = reference.Select(typeModifiersExpression); while(modifiers.MoveNext()) WriteTypeReference(modifiers.Current, writer); break; case "specialization": writer.WriteString("<"); XPathNodeIterator arguments = reference.Select(specializationArgumentsExpression); while(arguments.MoveNext()) { if(arguments.CurrentPosition > 1) writer.WriteString(", "); WriteTypeReference(arguments.Current, writer); } writer.WriteString(">"); break; } }
/// <summary> /// Write type syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteTypeSyntax(XPathNavigator reflection, SyntaxWriter writer) { string subgroup = (string)reflection.Evaluate(apiSubgroupExpression); switch(subgroup) { case "class": WriteClassSyntax(reflection, writer); break; case "structure": WriteStructureSyntax(reflection, writer); break; case "interface": WriteInterfaceSyntax(reflection, writer); break; case "delegate": WriteDelegateSyntax(reflection, writer); break; case "enumeration": WriteEnumerationSyntax(reflection, writer); break; } }
/// <summary> /// Write out a normal type reference /// </summary> /// <param name="api">The type reference to output</param> /// <param name="writer">The syntax writer to which the type reference is written</param> protected virtual void WriteNormalTypeReference(string api, SyntaxWriter writer) { switch(api) { case "T:System.Void": writer.WriteReferenceLink(api, "void"); break; case "T:System.String": writer.WriteReferenceLink(api, "string"); break; case "T:System.Boolean": writer.WriteReferenceLink(api, "bool"); break; case "T:System.Byte": writer.WriteReferenceLink(api, "byte"); break; case "T:System.SByte": writer.WriteReferenceLink(api, "sbyte"); break; case "T:System.Char": writer.WriteReferenceLink(api, "char"); break; case "T:System.Int16": writer.WriteReferenceLink(api, "short"); break; case "T:System.Int32": writer.WriteReferenceLink(api, "int"); break; case "T:System.Int64": writer.WriteReferenceLink(api, "long"); break; case "T:System.UInt16": writer.WriteReferenceLink(api, "ushort"); break; case "T:System.UInt32": writer.WriteReferenceLink(api, "uint"); break; case "T:System.UInt64": writer.WriteReferenceLink(api, "ulong"); break; case "T:System.Single": writer.WriteReferenceLink(api, "float"); break; case "T:System.Double": writer.WriteReferenceLink(api, "double"); break; case "T:System.Decimal": writer.WriteReferenceLink(api, "decimal"); break; default: writer.WriteReferenceLink(api); break; } }
/// <summary> /// Write method syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteMethodSyntax(XPathNavigator reflection, SyntaxWriter writer) { bool isSpecialName = (bool)reflection.Evaluate(apiIsSpecialExpression); string name = (string)reflection.Evaluate(apiNameExpression); if(isSpecialName) { string subsubgroup = (string)reflection.Evaluate(apiSubsubgroupExpression); if(subsubgroup == "operator") if(name == "Implicit" || name == "Explicit") WriteCastSyntax(reflection, writer); else WriteOperatorSyntax(reflection, writer); // Write out let properties (no .Net equivalent) as methods if(name.StartsWith("let_", StringComparison.Ordinal)) WriteNormalMethodSyntax(reflection, writer); } else WriteNormalMethodSyntax(reflection, writer); }
/// <summary> /// Write out a constant's value /// </summary> /// <param name="parent">The parent node</param> /// <param name="writer">The syntax writer</param> protected virtual void WriteConstantValue(XPathNavigator parent, SyntaxWriter writer) { XPathNavigator type = parent.SelectSingleNode(returnsTypeExpression); XPathNavigator value = parent.SelectSingleNode(returnsValueExpression); switch(value.LocalName) { case "nullValue": writer.WriteKeyword("null"); break; case "enumValue": XPathNodeIterator fields = value.SelectChildren(XPathNodeType.Element); while(fields.MoveNext()) { string name = fields.Current.GetAttribute("name", String.Empty); if(fields.CurrentPosition > 1) writer.WriteString("|"); this.WriteTypeReference(type, writer); writer.WriteString("."); writer.WriteString(name); } break; case "value": string text = value.Value; string typeId = type.GetAttribute("api", String.Empty); switch(typeId) { case "T:System.String": writer.WriteString("\""); writer.WriteString(text); writer.WriteString("\""); break; case "T:System.Boolean": writer.WriteKeyword(Convert.ToBoolean(text, CultureInfo.InvariantCulture) ? "true" : "false"); break; case "T:System.Char": writer.WriteString("'"); writer.WriteString(text); writer.WriteString("'"); break; // Decimal constants get converted to static read-only fields so no need to handle them here case "T:System.Byte": case "T:System.Double": case "T:System.SByte": case "T:System.Int16": case "T:System.Int64": case "T:System.Int32": case "T:System.UInt16": case "T:System.UInt32": case "T:System.UInt64": writer.WriteString(text); break; case "T:System.Single": writer.WriteString(text); writer.WriteString("f"); break; default: // If not a recognized type, just write out the value so that something shows writer.WriteString(text); break; } break; } }
/// <summary> /// Write interface syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public abstract void WriteInterfaceSyntax(XPathNavigator reflection, SyntaxWriter writer);
/// <summary> /// Write attached event syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> public virtual void WriteAttachedEventSyntax(XPathNavigator reflection, SyntaxWriter writer) { string adderId = (string)reflection.Evaluate(attachedEventAdderExpression); string removerId = (string)reflection.Evaluate(attachedEventRemoverExpression); if(!(string.IsNullOrEmpty(adderId) && string.IsNullOrEmpty(removerId))) { writer.WriteString("See "); writer.WriteReferenceLink(adderId); writer.WriteString(", "); writer.WriteReferenceLink(removerId); } }
/// <summary> /// Write unsupported unsafe code syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> /// <returns>True if unsupported, false if it is supported</returns> protected virtual bool IsUnsupportedUnsafe(XPathNavigator reflection, SyntaxWriter writer) { bool isUnsafe = (bool)reflection.Evaluate(apiIsUnsafeExpression); if(isUnsafe) writer.WriteMessage("UnsupportedUnsafe_" + this.Language); return isUnsafe; }
/// <summary> /// Write unsupported explicit implementation syntax /// </summary> /// <param name="reflection">The reflection data used to produce the syntax</param> /// <param name="writer">The writer to which the syntax is written</param> /// <returns>True if unsupported, false if it is supported</returns> protected virtual bool IsUnsupportedExplicit(XPathNavigator reflection, SyntaxWriter writer) { bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression); if(isExplicit) writer.WriteMessage("UnsupportedExplicit_" + this.Language); return isExplicit; }
/// <inheritdoc /> public override void WriteConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer) { throw new System.NotImplementedException(); }