diff options
Diffstat (limited to 'tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs')
-rw-r--r-- | tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs new file mode 100644 index 0000000..e0f3c07 --- /dev/null +++ b/tools/Sandcastle/Source/BuildAssembler/SyntaxComponents/ScriptSharpDeclarationSyntax.cs @@ -0,0 +1,611 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +using System; +using System.Xml.XPath; +using System.Globalization; + +namespace Microsoft.Ddue.Tools { + /// <summary> + /// Generates syntax that corresponds to JavaScript that Script# generates. + /// </summary> + public class ScriptSharpDeclarationSyntaxGenerator : SyntaxGeneratorTemplate { + private static readonly XPathExpression typeIsRecordExpression = XPathExpression.Compile("boolean(apidata/@record)"); + + private static readonly XPathExpression memberIsGlobalExpression = XPathExpression.Compile("boolean(apidata/@global)"); + + /// <summary> + /// Initializes a new instance of the <c>ScriptSharpDeclarationSyntaxGenerator</c> class. + /// </summary> + /// <param name="configuration"></param> + public ScriptSharpDeclarationSyntaxGenerator(XPathNavigator configuration) : base(configuration) { + if (String.IsNullOrEmpty(language)) language = "JavaScript"; + } + + /// <summary> + /// Determines whether the feature is unsupported by this language. + /// </summary> + /// <param name="reflection"></param> + /// <param name="writer"></param> + /// <returns></returns> + private bool IsUnsupported(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupportedGeneric(reflection, writer)) { + return true; + } + + if (IsUnsupportedExplicit(reflection, writer)) { + return true; + } + + if (IsUnsupportedUnsafe(reflection, writer)) { + return true; + } + + if (HasAttribute(reflection, "System.NonScriptableAttribute")) { + writer.WriteMessage("UnsupportedType_ScriptSharp"); + return true; + } + + return false; + } + + private string ReadNamespaceName(XPathNavigator reflection) { + return (string)reflection.Evaluate(apiContainingNamespaceNameExpression); + } + + private string ReadTypeName(XPathNavigator reflection) { + return (string)reflection.Evaluate(apiNameExpression); + } + + private string ReadContainingTypeName(XPathNavigator reflection) { + return (string)reflection.Evaluate(apiContainingTypeNameExpression); + } + + private string ReadFullTypeName(XPathNavigator reflection) { + string namespaceName = ReadNamespaceName(reflection); + + string typeName = ReadTypeName(reflection); + + if (String.IsNullOrEmpty(namespaceName) || HasAttribute(reflection, "System.IgnoreNamespaceAttribute")) { + return typeName; + } + else { + return String.Format("{0}.{1}", namespaceName, typeName); + } + } + + private string ReadFullContainingTypeName(XPathNavigator reflection) { + string namespaceName = ReadNamespaceName(reflection); + + string typeName = ReadContainingTypeName(reflection); + + if (String.IsNullOrEmpty(namespaceName) || HasAttribute(reflection, "System.IgnoreNamespaceAttribute")) { + return typeName; + } + else { + return String.Format("{0}.{1}", namespaceName, typeName); + } + } + + private string ReadMemberName(XPathNavigator reflection) { + string identifier = (string)reflection.Evaluate(apiNameExpression); + + if (!HasAttribute(reflection, "System.PreserveCaseAttribute")) { + identifier = CreateCamelCaseName(identifier); + } + + return identifier; + } + + private bool HasAttribute(XPathNavigator reflection, string attributeName) { + attributeName = "T:" + attributeName; + + XPathNodeIterator iterator = (XPathNodeIterator)reflection.Evaluate(apiAttributesExpression); + foreach (XPathNavigator navigator in iterator) { + XPathNavigator reference = navigator.SelectSingleNode(attributeTypeExpression); + if (reference.GetAttribute("api", string.Empty) == attributeName) { + return true; + } + } + + return false; + } + + public static string CreateCamelCaseName(string name) { + + if (String.IsNullOrEmpty(name)) { + return name; + } + + // Some exceptions that simply need to be special cased + if (name.Equals("ID", StringComparison.Ordinal)) { + return "id"; + } + + bool hasLowerCase = false; + int conversionLength = 0; + + for (int i = 0; i < name.Length; i++) { + if (Char.IsUpper(name, i)) { + conversionLength++; + } else { + hasLowerCase = true; + break; + } + } + + if (((hasLowerCase == false) && (name.Length != 1)) || (conversionLength == 0)) { + // Name is all upper case, or all lower case; leave it as-is. + return name; + } + + if (conversionLength > 1) { + // Convert the leading uppercase segment, except the last character + // which is assumed to be the first letter of the next word + return name.Substring(0, conversionLength - 1).ToLower(CultureInfo.InvariantCulture) + name.Substring(conversionLength - 1); + } + + else if (name.Length == 1) { + return name.ToLower(CultureInfo.InvariantCulture); + } + + else { + // Convert the leading upper case character to lower case + return Char.ToLower(name[0], CultureInfo.InvariantCulture) + name.Substring(1); + } + } + + private void WriteIndentedNewLine(SyntaxWriter writer) { + writer.WriteString(","); + writer.WriteLine(); + writer.WriteString("\t"); + } + + private void WriteParameterList(XPathNavigator reflection, SyntaxWriter writer) { + XPathNodeIterator parameters = reflection.Select(apiParametersExpression); + writer.WriteString("("); + + while (parameters.MoveNext()) { + XPathNavigator parameter = parameters.Current; + + WriteParameter(parameter, writer); + if (parameters.CurrentPosition < parameters.Count) { + writer.WriteString(", "); + } + } + writer.WriteString(")"); + } + + private void WriteParameter(XPathNavigator parameter, SyntaxWriter writer) { + string text = (string)parameter.Evaluate(parameterNameExpression); + XPathNavigator reference = parameter.SelectSingleNode(parameterTypeExpression); + if ((bool)parameter.Evaluate(parameterIsParamArrayExpression)) { + writer.WriteString("... "); + } + writer.WriteParameter(text); + } + + private void WriteTypeReference(XPathNavigator reference, SyntaxWriter writer) + { + switch (reference.LocalName) + { + case "arrayOf": + int rank = Convert.ToInt32(reference.GetAttribute("rank", string.Empty)); + XPathNavigator navigator = reference.SelectSingleNode(typeExpression); + WriteTypeReference(navigator, writer); + writer.WriteString("["); + for (int i = 1; i < rank; i++) { writer.WriteString(","); } + writer.WriteString("]"); + break; + case "type": + string id = reference.GetAttribute("api", string.Empty); + WriteNormalTypeReference(id, writer); + break; + case "pointerTo": + case "referenceTo": + case "template": + case "specialization": + // Not supported + break; + } + } + + private void WriteNormalTypeReference(string api, SyntaxWriter writer) { + switch (api) { + case "T:System.Byte": + writer.WriteReferenceLink(api, "Byte"); + return; + + case "T:System.SByte": + writer.WriteReferenceLink(api, "SByte"); + return; + + case "T:System.Char": + writer.WriteReferenceLink(api, "Char"); + return; + + case "T:System.Int16": + writer.WriteReferenceLink(api, "Int16"); + return; + + case "T:System.Int32": + writer.WriteReferenceLink(api, "Int32"); + return; + + case "T:System.Int64": + writer.WriteReferenceLink(api, "Int64"); + return; + + case "T:System.UInt16": + writer.WriteReferenceLink(api, "UInt16"); + return; + + case "T:System.UInt32": + writer.WriteReferenceLink(api, "UInt32"); + return; + + case "T:System.UInt64": + writer.WriteReferenceLink(api, "UInt64"); + return; + + case "T:System.Single": + writer.WriteReferenceLink(api, "Single"); + return; + + case "T:System.Double": + writer.WriteReferenceLink(api, "Double"); + return; + + case "T:System.Decimal": + writer.WriteReferenceLink(api, "Decimal"); + return; + + case "T:System.Boolean": + writer.WriteReferenceLink(api, "Boolean"); + return; + } + + // Remove 'T:' + string name = api.Substring(2); + + // Strip System namespaces + if (name.StartsWith("System.")) { + int idx = name.LastIndexOf('.'); + name = name.Substring(idx + 1); + } + + writer.WriteReferenceLink(api, name); + } + + private void WriteRecordSyntax(XPathNavigator reflection, SyntaxWriter writer) { + string namespaceName = ReadNamespaceName(reflection); + + string typeName = ReadTypeName(reflection); + + writer.WriteString(namespaceName); + writer.WriteString(".$create_"); + writer.WriteString(typeName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + writer.WriteString("();"); + } + + private void WriteRecordConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer) { + string namespaceName = ReadNamespaceName(reflection); + + string typeName = ReadContainingTypeName(reflection); + + writer.WriteString(namespaceName); + writer.WriteString(".$create_"); + writer.WriteString(typeName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + WriteParameterList(reflection, writer); + writer.WriteString(";"); + } + + public override void WriteClassSyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) return; + + if (HasAttribute(reflection, "System.RecordAttribute")) { + WriteRecordSyntax(reflection, writer); + return; + } + + string typeName = ReadFullTypeName(reflection); + + writer.WriteIdentifier(typeName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + writer.WriteString("();"); + + writer.WriteLine(); + writer.WriteLine(); + + writer.WriteIdentifier("Type"); + writer.WriteString(".createClass("); + writer.WriteLine(); + writer.WriteString("\t'"); + writer.WriteString(typeName); + writer.WriteString("'"); + + bool hasBaseClass = false; + + // Write the base class. + XPathNavigator reference = reflection.SelectSingleNode(apiBaseClassExpression); + if (!((reference == null) || ((bool)reference.Evaluate(typeIsObjectExpression)))) { + WriteIndentedNewLine(writer); + WriteTypeReference(reference, writer); + hasBaseClass = true; + } + + // Write the interfaces. + XPathNodeIterator iterator = reflection.Select(apiImplementedInterfacesExpression); + if (iterator.Count != 0) { + if (!hasBaseClass) { + WriteIndentedNewLine(writer); + writer.WriteString("null"); + } + + WriteIndentedNewLine(writer); + + while (iterator.MoveNext()) { + XPathNavigator interfaceRef = iterator.Current; + WriteTypeReference(interfaceRef, writer); + if (iterator.CurrentPosition < iterator.Count) { + WriteIndentedNewLine(writer); + } + } + } + + writer.WriteString(");"); + } + + public override void WriteConstructorSyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) { + return; + } + + bool isRecord = (bool)reflection.Evaluate(typeIsRecordExpression); + + if (isRecord) { + WriteRecordConstructorSyntax(reflection, writer); + return; + } + + string typeName = ReadFullContainingTypeName(reflection); + + writer.WriteIdentifier(typeName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + WriteParameterList(reflection, writer); + writer.WriteString(";"); + } + + public override void WriteNormalMethodSyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) return; + + if (HasAttribute(reflection, "System.AttachedPropertyAttribute")) { + WriteAttachedPropertySyntax(reflection, writer); + return; + } + + string memberName = ReadMemberName(reflection); + + bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression); + bool isGlobal = (bool)reflection.Evaluate(memberIsGlobalExpression); + + if (isStatic && !isGlobal) { + writer.WriteIdentifier(ReadFullContainingTypeName(reflection)); + writer.WriteString("."); + writer.WriteIdentifier(memberName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + } + else { + writer.WriteKeyword("function"); + writer.WriteString(" "); + writer.WriteIdentifier(memberName); + } + + WriteParameterList(reflection, writer); + writer.WriteString(";"); + } + + public override void WriteDelegateSyntax(XPathNavigator reflection, SyntaxWriter writer) { + writer.WriteKeyword("function"); + WriteParameterList(reflection, writer); + writer.WriteString(";"); + } + + public override void WriteEnumerationSyntax(XPathNavigator reflection, SyntaxWriter writer) { + string typeName = ReadFullTypeName(reflection); + + writer.WriteIdentifier(typeName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + writer.WriteString("();"); + + writer.WriteLine(); + + writer.WriteIdentifier(typeName); + writer.WriteString(".createEnum('"); + writer.WriteIdentifier(typeName); + writer.WriteString("', "); + writer.WriteString(HasAttribute(reflection, "System.FlagsAttribute") ? "true" : "false"); + writer.WriteString(");"); + } + + public override void WriteEventSyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) return; + + if (reflection.Select(apiParametersExpression).Count > 0) { + writer.WriteMessage("UnsupportedIndex_" + Language); + return; + } + + string memberName = ReadMemberName(reflection); + + writer.WriteKeyword("function"); + writer.WriteString(" add_"); + writer.WriteIdentifier(memberName); + writer.WriteString("("); + writer.WriteParameter("value"); + writer.WriteString(");"); + + writer.WriteLine(); + + writer.WriteKeyword("function"); + writer.WriteString(" remove_"); + writer.WriteIdentifier(memberName); + writer.WriteString("("); + writer.WriteParameter("value"); + writer.WriteString(");"); + } + + public override void WriteFieldSyntax(XPathNavigator reflection, SyntaxWriter writer) + { + if (IsUnsupported(reflection, writer)) { + return; + } + + string memberName = ReadMemberName(reflection); + + bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression); + if (isStatic) { + string typeName = ReadFullContainingTypeName(reflection); + + writer.WriteIdentifier(typeName); + writer.WriteString("."); + } + + writer.WriteIdentifier(memberName); + } + + public override void WriteInterfaceSyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) return; + + string typeName = ReadFullTypeName(reflection); + + writer.WriteIdentifier(typeName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + writer.WriteString("();"); + + writer.WriteLine(); + + writer.WriteIdentifier(typeName); + writer.WriteString(".createInterface('"); + writer.WriteIdentifier(typeName); + writer.WriteString("');"); + } + + public override void WriteAttachedEventSyntax(XPathNavigator reflection, SyntaxWriter writer) { + // Not supported + } + + public override void WriteAttachedPropertySyntax(XPathNavigator reflection, SyntaxWriter writer) { + string typeName = ReadContainingTypeName(reflection); + + string methodName = ReadMemberName(reflection); + + string propertyName = String.Format("{0}.{1}", typeName, methodName.Substring(3)); + + if (methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase)) { + writer.WriteKeyword("var"); + writer.WriteString(" value = obj['"); + writer.WriteString(propertyName); + writer.WriteString("'];"); + } + else if (methodName.StartsWith("Set", StringComparison.OrdinalIgnoreCase)) { + writer.WriteString("obj['"); + writer.WriteString(propertyName); + writer.WriteString("'] = value;"); + } + } + + 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 WriteNamespaceSyntax(XPathNavigator reflection, SyntaxWriter writer) { + string name = reflection.Evaluate(apiNameExpression).ToString(); + + writer.WriteString("Type.createNamespace('"); + writer.WriteIdentifier(name); + writer.WriteString("');"); + } + + public override void WritePropertySyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) return; + + if (HasAttribute(reflection, "System.IntrinsicPropertyAttribute")) { + WriteFieldSyntax(reflection, writer); + return; + } + + string memberName = ReadMemberName(reflection); + + bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression); + + bool isGetter = (bool)reflection.Evaluate(apiIsReadPropertyExpression); + bool isSetter = (bool)reflection.Evaluate(apiIsWritePropertyExpression); + + XPathNavigator reference = reflection.SelectSingleNode(apiReturnTypeExpression); + + if (isGetter) { + if (isStatic) { + writer.WriteIdentifier(ReadFullContainingTypeName(reflection)); + writer.WriteString("."); + + writer.WriteString("get_"); + writer.WriteIdentifier(memberName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + } + else { + writer.WriteKeyword("function"); + writer.WriteString(" "); + + writer.WriteString("get_"); + writer.WriteIdentifier(memberName); + } + + WriteParameterList(reflection, writer); + writer.WriteString(";"); + writer.WriteLine(); + } + + if (isSetter) { + if (isStatic) { + writer.WriteIdentifier(ReadFullContainingTypeName(reflection)); + writer.WriteString("."); + + writer.WriteString("set_"); + writer.WriteIdentifier(memberName); + writer.WriteString(" = "); + writer.WriteKeyword("function"); + } + else { + writer.WriteKeyword("function"); + writer.WriteString(" "); + + writer.WriteString("set_"); + writer.WriteIdentifier(memberName); + } + + writer.WriteString("("); + writer.WriteParameter("value"); + writer.WriteString(");"); + } + } + + public override void WriteStructureSyntax(XPathNavigator reflection, SyntaxWriter writer) { + if (IsUnsupported(reflection, writer)) return; + writer.WriteMessage("UnsupportedStructure_" + Language); + } + } +}
\ No newline at end of file |