// Copyright (c) Microsoft Corporation. All rights reserved. // using System; using System.Xml.XPath; namespace Microsoft.Ddue.Tools { public class JScriptDeclarationSyntaxGenerator : SyntaxGeneratorTemplate { public JScriptDeclarationSyntaxGenerator (XPathNavigator configuration) : base(configuration) { if (String.IsNullOrEmpty(language)) language = "JScript"; } public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) { string name = (string)reflection.Evaluate(apiNameExpression); writer.WriteKeyword("package"); writer.WriteString(" "); writer.WriteIdentifier(name); } public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; string name = (string)reflection.Evaluate(apiNameExpression); bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractTypeExpression); bool isSealed = (bool)reflection.Evaluate(apiIsSealedTypeExpression); WriteAttributeList(reflection, writer); WriteAccessModifier(reflection, writer); if (isSealed) { writer.WriteKeyword("final"); writer.WriteString(" "); } else if (isAbstract) { writer.WriteKeyword("abstract"); writer.WriteString(" "); } writer.WriteKeyword("class"); writer.WriteString(" "); writer.WriteString(name); WriteBaseClass(reflection, writer); WriteInterfaceList(reflection, writer); } public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; writer.WriteMessage("UnsupportedStructure_" + Language); } public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; string name = (string)reflection.Evaluate(apiNameExpression); WriteAttributeList(reflection, writer); WriteAccessModifier(reflection, writer); writer.WriteKeyword("interface"); writer.WriteString(" "); writer.WriteString(name); WriteInterfaceList("extends", reflection, writer); } public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedGeneric(reflection, writer)) return; writer.WriteMessage("UnsupportedDelegate_" + Language); } public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) { string name = (string)reflection.Evaluate(apiNameExpression); WriteAttributeList(reflection, writer); WriteAccessModifier(reflection, writer); writer.WriteKeyword("enum"); writer.WriteString(" "); writer.WriteString(name); // no JScript support for underlying types } public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) { bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression); if (isStatic) { writer.WriteMessage("UnsupportedStaticConstructor_" + Language); } else { if (IsUnsupportedUnsafe(reflection, writer)) return; XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression); WriteAttributeList(reflection, writer); WriteAccessModifier(reflection, writer); writer.WriteKeyword("function"); writer.WriteString(" "); WriteTypeReference(declaringType, writer); WriteParameterList(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); XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression); WriteAttributeList(reflection, writer); WriteProcedureModifiers(reflection, writer); writer.WriteKeyword("function"); writer.WriteString(" "); writer.WriteIdentifier(name); WriteParameterList(reflection, writer); if (returnType != null) { writer.WriteString(" : "); WriteTypeReference(returnType, writer); } } public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; if (IsUnsupportedExplicit(reflection, writer)) return; if (reflection.Select(apiParametersExpression).Count > 0) { writer.WriteMessage("UnsupportedIndex_" + Language); return; } string name = (string)reflection.Evaluate(apiNameExpression); bool isGettable = (bool)reflection.Evaluate(apiIsReadPropertyExpression); bool isSettable = (bool)reflection.Evaluate(apiIsWritePropertyExpression); XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression); if (isGettable) { WriteAttributeList(reflection, writer); WriteProcedureModifiers(reflection, writer); writer.WriteKeyword("function get"); writer.WriteString(" "); writer.WriteIdentifier(name); writer.WriteString(" () : "); WriteTypeReference(type, writer); writer.WriteLine(); } if (isSettable) { WriteAttributeList(reflection, writer); WriteProcedureModifiers(reflection, writer); writer.WriteKeyword("function set"); writer.WriteString(" "); writer.WriteIdentifier(name); writer.WriteString(" ("); writer.WriteParameter("value"); writer.WriteString(" : "); WriteTypeReference(type, writer); writer.WriteString(")"); } } public override void WriteFieldSyntax (XPathNavigator reflection, SyntaxWriter writer) { if (IsUnsupportedUnsafe(reflection, writer)) return; 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); XPathNavigator type = reflection.SelectSingleNode(apiReturnTypeExpression); WriteAttributeList(reflection, writer); WriteAccessModifier(reflection, writer); if (isStatic) { if (isLiteral) { writer.WriteKeyword("const"); } else { writer.WriteKeyword("static"); } writer.WriteString(" "); } if (isInitOnly) { writer.WriteKeyword("final"); writer.WriteString(" "); } writer.WriteKeyword("var"); writer.WriteString(" "); writer.WriteIdentifier(name); writer.WriteString(" : "); WriteTypeReference(type, writer); } public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) { writer.WriteMessage("UnsupportedOperator_" + Language); } public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) { writer.WriteMessage("UnsupportedCast_" + Language); } public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) { writer.WriteMessage("UnsupportedEvent_" + Language); } private void WriteBaseClass (XPathNavigator reflection, SyntaxWriter writer) { XPathNavigator baseClass = reflection.SelectSingleNode(apiBaseClassExpression); if ((baseClass != null) && !((bool)baseClass.Evaluate(typeIsObjectExpression))) { writer.WriteString(" "); writer.WriteKeyword("extends"); writer.WriteString(" "); WriteTypeReference(baseClass, writer); } } private void WriteInterfaceList (XPathNavigator reflection, SyntaxWriter writer) { WriteInterfaceList("implements", reflection, writer); } private void WriteInterfaceList (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(", "); } } private void WriteProcedureModifiers (XPathNavigator reflection, SyntaxWriter writer) { // interface members don't get modified string typeSubgroup = (string)reflection.Evaluate(apiContainingTypeSubgroupExpression); if (typeSubgroup == "interface") return; WriteAccessModifier(reflection, writer); // instance or virtual, static or abstract, etc. 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); if (isStatic) { writer.WriteKeyword("static"); writer.WriteString(" "); } else { // all members are virtual in JScript, so no virtual keyword is required if (isVirtual) { if (isAbstract) { writer.WriteKeyword("abstract"); writer.WriteString(" "); } else { if (isOverride) { writer.WriteKeyword("override"); writer.WriteString(" "); } if (isFinal) { writer.WriteKeyword("final"); writer.WriteString(" "); } } } } } private void WriteParameterList (XPathNavigator reflection, SyntaxWriter writer) { WriteParameterList(reflection, writer, true); } private void WriteParameterList (XPathNavigator reflection, SyntaxWriter writer, bool newlines) { XPathNodeIterator parameters = reflection.Select(apiParametersExpression); writer.WriteString("("); if (newlines && (parameters.Count > 0)) writer.WriteLine(); while (parameters.MoveNext()) { XPathNavigator parameter = parameters.Current; if (newlines) writer.WriteString("\t"); WriteParameter(parameter, writer); if (parameters.CurrentPosition < parameters.Count) writer.WriteString(", "); if (newlines) writer.WriteLine(); } writer.WriteString(")"); } // JScript has no in, out, optional, or reference parameters private void WriteParameter (XPathNavigator parameter, SyntaxWriter writer) { string name = (string)parameter.Evaluate(parameterNameExpression); XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression); bool isParamArray = (bool)parameter.Evaluate(parameterIsParamArrayExpression); if (isParamArray) { writer.WriteString("... "); } writer.WriteParameter(name); writer.WriteString(" : "); WriteTypeReference(type, writer); } private void WriteAccessModifier (XPathNavigator reflection, SyntaxWriter writer) { string visibility = reflection.Evaluate(apiVisibilityExpression).ToString(); switch (visibility) { case "public": writer.WriteKeyword("public"); break; case "family": writer.WriteKeyword("protected"); break; case "family or assembly": writer.WriteKeyword("protected internal"); break; case "assembly": writer.WriteKeyword("internal"); break; case "private": writer.WriteKeyword("private"); break; case "family and assembly": // this isn't handled in JScript break; } writer.WriteString(" "); } 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 < 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; } } private void WriteNormalTypeReference (string api, SyntaxWriter writer) { switch (api) { case "T:System.Boolean": writer.WriteReferenceLink(api, "boolean"); 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; } } private void WriteAttributeList (XPathNavigator reflection, SyntaxWriter writer) { // fill in this logic } } }