// Copyright © Microsoft Corporation. // This source file is subject to the Microsoft Permissive License. // See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx. // All other rights reserved. using System; using System.Collections.Generic; using System.Xml.XPath; namespace Microsoft.Ddue.Tools { public class JSharpDeclarationSyntaxGenerator : DeclarationSyntaxGeneratorTemplate { public JSharpDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) { if (String.IsNullOrEmpty(Language)) Language = "JSharp"; } // private static string unsupportedGeneric = "UnsupportedGeneric_JSharp"; public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) { string name = reflection.Evaluate(apiNameExpression).ToString(); writer.WriteKeyword("package"); writer.WriteString(" "); writer.WriteIdentifier(name); } public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; string name = reflection.Evaluate(apiNameExpression).ToString(); bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractTypeExpression); bool isSealed = (bool) reflection.Evaluate(apiIsSealedTypeExpression); bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression); if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer); WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); if (isSealed) { writer.WriteKeyword("final"); writer.WriteString(" "); } else if (isAbstract) { writer.WriteKeyword("abstract"); writer.WriteString(" "); } writer.WriteKeyword("class"); writer.WriteString(" "); writer.WriteIdentifier(name); XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression); if ((baseClass != null) && !((bool) baseClass.Evaluate(typeIsObjectExpression))) { writer.WriteString(" "); writer.WriteKeyword("extends"); writer.WriteString(" "); WriteTypeReference(baseClass, writer); } WriteImplementedInterfaces(reflection, writer); } public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; string name = (string) reflection.Evaluate(apiNameExpression); bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression); if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer); WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); writer.WriteKeyword("final"); writer.WriteString(" "); writer.WriteKeyword("class"); writer.WriteString(" "); writer.WriteIdentifier(name); writer.WriteString(" "); writer.WriteKeyword("extends"); writer.WriteString(" "); writer.WriteReferenceLink("T:System.ValueType"); WriteImplementedInterfaces(reflection, writer); } public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; string name = (string) reflection.Evaluate(apiNameExpression); WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); writer.WriteKeyword("interface"); writer.WriteString(" "); writer.WriteIdentifier(name); WriteImplementedInterfaces("extends", reflection, writer); } public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; if (IsUnsupportedGeneric(reflection, writer)) return; string name = (string) reflection.Evaluate(apiNameExpression); bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression); writer.WriteString("/** @delegate */"); writer.WriteLine(); if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer); WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); writer.WriteKeyword("delegate"); writer.WriteString(" "); WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier(name); WriteMethodParameters(reflection, writer); } public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) { string name = (string) reflection.Evaluate(apiNameExpression); bool isSerializable = (bool) reflection.Evaluate(apiIsSerializableTypeExpression); if (isSerializable) WriteAttribute("T:System.SerializableAttribute", writer); WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); writer.WriteKeyword("enum"); writer.WriteString(" "); writer.WriteIdentifier(name); } public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; string name = (string) reflection.Evaluate(apiContainingTypeNameExpression); bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression); if (isStatic) { // no static constructors in Java writer.WriteMessage("UnsupportedStaticConstructor_" + Language); return; } WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier(name); WriteMethodParameters(reflection, writer); } public override void WriteMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) { bool isSpecialName = (bool) reflection.Evaluate(apiIsSpecialExpression); if (isSpecialName) { writer.WriteMessage("UnsupportedOperator_" + Language); } else { WriteNormalMethodSyntax(reflection, writer); } } public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; if (IsUnsupportedGeneric(reflection, writer)) return; if (IsUnsupportedExplicit(reflection, writer)) return; string name = (string) reflection.Evaluate(apiNameExpression); WriteAttributes(reflection, writer); WriteProcedureModifiers(reflection, writer); WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier(name); WriteMethodParameters(reflection, writer); } private void WriteNamedNormalMethodSyntax (string name, XPathNavigator reflection, SyntaxWriter writer) { } public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; if (IsUnsupportedExplicit(reflection, writer)) return; string name = (string) reflection.Evaluate(apiNameExpression); bool isGettable = (bool) reflection.Evaluate(apiIsReadPropertyExpression); bool isSettable = (bool) reflection.Evaluate(apiIsWritePropertyExpression); if (isGettable) { writer.WriteString("/** @property */"); writer.WriteLine(); // write getter method WriteAttributes(reflection, writer); WriteProcedureModifiers(reflection, writer); WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier("get_" + name); WriteMethodParameters(reflection, writer); writer.WriteLine(); } if (isSettable) { writer.WriteString("/** @property */"); writer.WriteLine(); // write setter method WriteAttributes(reflection, writer); WriteProcedureModifiers(reflection, writer); writer.WriteString(" "); writer.WriteKeyword("void"); writer.WriteString(" "); writer.WriteIdentifier("set_" + name); // parameters writer.WriteString("("); WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteParameter("value"); writer.WriteString(")"); // end parameters writer.WriteLine(); } } public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; string name = (string) reflection.Evaluate(apiNameExpression); XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression); writer.WriteString("/** @event */"); writer.WriteLine(); // add_ method declaration WriteAttributes(reflection, writer); WriteProcedureModifiers(reflection, writer); WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier("add_" + name); writer.WriteString(" ("); WriteTypeReference(handler, writer); writer.WriteString(" "); writer.WriteParameter("value"); writer.WriteString(")"); writer.WriteLine(); writer.WriteString("/** @event */"); writer.WriteLine(); // remove_ method declaration WriteAttributes(reflection, writer); WriteProcedureModifiers(reflection, writer); WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier("remove_" + name); writer.WriteString(" ("); WriteTypeReference(handler, writer); writer.WriteString(" "); writer.WriteParameter("value"); writer.WriteString(")"); writer.WriteLine(); } private void WriteProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) { // interface members don't get modified string typeSubgroup = (string) reflection.Evaluate(apiContainingTypeSubgroupExpression); if (typeSubgroup == "interface") return; bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression); bool isVirtual = (bool) reflection.Evaluate(apiIsVirtualExpression); bool isAbstract = (bool) reflection.Evaluate(apiIsAbstractProcedureExpression); bool isFinal = (bool) reflection.Evaluate(apiIsFinalExpression); // bool isOverride = (bool) reflection.Evaluate(apiIsOverrideExpression); WriteVisibility(reflection, writer); writer.WriteString(" "); if (isStatic) { writer.WriteKeyword("static"); writer.WriteString(" "); } else { if (isVirtual) { if (isAbstract) { writer.WriteKeyword("abstract"); writer.WriteString(" "); } else if (isFinal) { writer.WriteKeyword("final"); writer.WriteString(" "); } } } } public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) { string name = (string) reflection.Evaluate(apiNameExpression); bool isStatic = (bool) reflection.Evaluate(apiIsStaticExpression); bool isLiteral = (bool) reflection.Evaluate(apiIsLiteralFieldExpression); bool isInitOnly = (bool) reflection.Evaluate(apiIsInitOnlyFieldExpression); bool isSerialized = (bool) reflection.Evaluate(apiIsSerializedFieldExpression); if (!isSerialized) WriteAttribute("T:System.NonSerializedAttribute", writer); WriteAttributes(reflection, writer); WriteVisibility(reflection, writer); writer.WriteString(" "); // Java doesn't support literals as distinct from static initonly if (isStatic) { writer.WriteKeyword("static"); writer.WriteString(" "); } if (isLiteral || isInitOnly) { writer.WriteKeyword("final"); writer.WriteString(" "); } WriteReturnValue(reflection, writer); writer.WriteString(" "); writer.WriteIdentifier(name); } // Visibility protected override void WriteVisibility (XPathNavigator reflection, SyntaxWriter writer) { string visibility = reflection.Evaluate(apiVisibilityExpression).ToString(); switch (visibility) { case "public": writer.WriteKeyword("public"); break; case "family": // in Java, protected = family or assembly writer.WriteKeyword("protected"); break; case "family or assembly": writer.WriteKeyword("protected"); break; case "assembly": // no assembly-only access in Java break; case "private": writer.WriteKeyword("private"); break; } } // Attributes private void WriteAttribute (string reference, SyntaxWriter writer) { WriteAttribute(reference, writer, true); } private void WriteAttribute (string reference, SyntaxWriter writer, bool newline) { writer.WriteString("/** @attribute "); writer.WriteReferenceLink(reference); writer.WriteString(" */ "); if (newline) writer.WriteLine(); } private void WriteAttributes (XPathNavigator reflection, SyntaxWriter writer) { XPathNodeIterator attributes = (XPathNodeIterator) reflection.Evaluate(apiAttributesExpression); foreach (XPathNavigator attribute in attributes) { XPathNavigator type = attribute.SelectSingleNode(attributeTypeExpression); writer.WriteString("/** @attribute "); WriteTypeReference(type, writer); XPathNodeIterator arguments = (XPathNodeIterator) attribute.Select(attributeArgumentsExpression); XPathNodeIterator assignments = (XPathNodeIterator) attribute.Select(attributeAssignmentsExpression); if ((arguments.Count > 0) || (assignments.Count > 0)) { writer.WriteString("("); while (arguments.MoveNext()) { XPathNavigator argument = arguments.Current; if (arguments.CurrentPosition > 1) writer.WriteString(", "); WriteValue(argument, writer); } if ((arguments.Count > 0) && (assignments.Count > 0)) writer.WriteString(", "); while (assignments.MoveNext()) { XPathNavigator assignment = assignments.Current; if (assignments.CurrentPosition > 1) writer.WriteString(", "); writer.WriteString((string) assignment.Evaluate(assignmentNameExpression)); writer.WriteString(" = "); WriteValue(assignment, writer); } writer.WriteString(")"); } writer.WriteString(" */"); writer.WriteLine(); } } private void WriteValue (XPathNavigator parent, SyntaxWriter writer) { XPathNavigator type = parent.SelectSingleNode(attributeTypeExpression); XPathNavigator value = parent.SelectSingleNode(valueExpression); // if (value == null) Console.WriteLine("null value"); switch (value.LocalName) { case "nullValue": writer.WriteKeyword("null"); break; case "typeValue": // this isn't really supported in J#; there is no compile-time way to get a type representation // writer.WriteKeyword("typeof"); // writer.WriteString("("); WriteTypeReference(value.SelectSingleNode(typeExpression), writer); // writer.WriteString(")"); 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("|"); 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": bool bool_value = Convert.ToBoolean(text); if (bool_value) { writer.WriteKeyword("true"); } else { writer.WriteKeyword("false"); } break; case "T:System.Char": writer.WriteString("'"); writer.WriteString(text); writer.WriteString("'"); break; } break; } } // Interfaces private void WriteImplementedInterfaces (XPathNavigator reflection, SyntaxWriter writer) { WriteImplementedInterfaces("implements", reflection, writer); } private void WriteImplementedInterfaces (string keyword, XPathNavigator reflection, SyntaxWriter writer) { XPathNodeIterator implements = reflection.Select(apiImplementedInterfacesExpression); if (implements.Count == 0) return; writer.WriteString(" "); writer.WriteKeyword(keyword); writer.WriteString(" "); while (implements.MoveNext()) { XPathNavigator implement = implements.Current; WriteTypeReference(implement, writer); if (implements.CurrentPosition < implements.Count) { writer.WriteString(", "); if (writer.Position > maxPosition) { writer.WriteLine(); writer.WriteString("\t"); } } } } // Parameters private void WriteMethodParameters (XPathNavigator reflection, SyntaxWriter writer) { XPathNodeIterator parameters = reflection.Select(apiParametersExpression); writer.WriteString("("); if (parameters.Count > 0) { writer.WriteLine(); WriteParameters(parameters, reflection, writer); } writer.WriteString(")"); } private void WriteParameters (XPathNodeIterator parameters, XPathNavigator reflection, SyntaxWriter writer) { while (parameters.MoveNext()) { XPathNavigator parameter = parameters.Current; string name = (string) parameter.Evaluate(parameterNameExpression); XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression); bool isIn = (bool) parameter.Evaluate(parameterIsInExpression); bool isOut = (bool) parameter.Evaluate(parameterIsOutExpression); bool isRef = (bool) parameter.Evaluate(parameterIsRefExpression); // bool isParamArray = (bool) parameter.Evaluate(parameterIsParamArrayExpression); writer.WriteString("\t"); if (isIn) WriteAttribute("T:System.Runtime.InteropServices.InAttribute", writer, false); if (isOut) WriteAttribute("T:System.Runtime.InteropServices.OutAttribute", writer, false); if (isRef) { writer.WriteString("/** @ref */"); } WriteTypeReference(type, writer); writer.WriteString(" "); writer.WriteParameter(name); if (parameters.CurrentPosition < parameters.Count) writer.WriteString(","); writer.WriteLine(); } } // Return Value private void WriteReturnValue (XPathNavigator reflection, SyntaxWriter writer) { XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression); if (type == null) { writer.WriteKeyword("void"); } else { WriteTypeReference(type, writer); } } // References private void WriteTypeReference (XPathNavigator reference, SyntaxWriter writer) { switch (reference.LocalName) { case "arrayOf": int rank = Convert.ToInt32( reference.GetAttribute("rank",String.Empty) ); XPathNavigator element = reference.SelectSingleNode(typeExpression); WriteTypeReference(element, writer); writer.WriteString("["); for (int i=1; i 1) writer.WriteString(", "); WriteTypeReference(arguments.Current, writer); } writer.WriteString(">"); break; } } private void WriteNormalTypeReference (string reference, SyntaxWriter writer) { switch (reference) { case "T:System.Void": writer.WriteReferenceLink(reference, "void"); break; case "T:System.Boolean": writer.WriteReferenceLink(reference, "boolean"); break; case "T:System.Byte": writer.WriteReferenceLink(reference, "byte"); break; case "T:System.Char": writer.WriteReferenceLink(reference, "char"); break; case "T:System.Int16": writer.WriteReferenceLink(reference, "short"); break; case "T:System.Int32": writer.WriteReferenceLink(reference, "int"); break; case "T:System.Int64": writer.WriteReferenceLink(reference, "long"); break; case "T:System.Single": writer.WriteReferenceLink(reference, "float"); break; case "T:System.Double": writer.WriteReferenceLink(reference, "double"); break; default: writer.WriteReferenceLink(reference); break; } } } }