// 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 VisualBasicUsageSyntaxGenerator : SyntaxGeneratorTemplate {
public VisualBasicUsageSyntaxGenerator (XPathNavigator configuration) : base(configuration) {
if (String.IsNullOrEmpty(Language)) Language = "VisualBasicUsage";
}
public override void WriteNamespaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
string name = (string)reflection.Evaluate(apiNameExpression);
writer.WriteKeyword("Imports");
writer.WriteString(" ");
writer.WriteIdentifier(name);
}
private void TypeDeclaration(XPathNavigator reflection, SyntaxWriter writer)
{
TypeDeclaration(reflection, writer, false);
}
private void TypeDeclaration (XPathNavigator reflection, SyntaxWriter writer, bool writeVariance) {
string name = (string)reflection.Evaluate(apiNameExpression);
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
writer.WriteKeyword("Dim");
writer.WriteString(" ");
writer.WriteParameter("instance");
writer.WriteString(" ");
writer.WriteKeyword("As");
writer.WriteString(" ");
if (declaringType != null) {
WriteTypeReference(declaringType, writer);
writer.WriteString(".");
}
if (reservedWords.ContainsKey(name)) {
writer.WriteString("[");
writer.WriteIdentifier(name);
writer.WriteString("]");
} else {
writer.WriteIdentifier(name);
}
WriteGenericTemplates(reflection, writer, writeVariance);
}
private void WriteGenericTemplates(XPathNavigator type, SyntaxWriter writer, bool writeVariance)
{
XPathNodeIterator templates = type.Select(apiTemplatesExpression);
if (templates.Count == 0) return;
writer.WriteString("(");
writer.WriteKeyword("Of");
writer.WriteString(" ");
while (templates.MoveNext())
{
XPathNavigator template = templates.Current;
if (templates.CurrentPosition > 1) writer.WriteString(", ");
if (writeVariance)
{
bool contravariant = (bool)template.Evaluate(templateIsContravariantExpression);
bool covariant = (bool)template.Evaluate(templateIsCovariantExpression);
if (contravariant)
{
writer.WriteKeyword("In");
writer.WriteString(" ");
}
if (covariant)
{
writer.WriteKeyword("Out");
writer.WriteString(" ");
}
}
string name = template.GetAttribute("name", String.Empty);
writer.WriteString(name);
}
writer.WriteString(")");
}
private void WriteGenericTemplates (XPathNavigator type, SyntaxWriter writer) {
WriteGenericTemplates(type, writer, false);
}
private void ParameterDeclaration (string name, XPathNavigator type, SyntaxWriter writer) {
writer.WriteKeyword("Dim");
writer.WriteString(" ");
writer.WriteParameter(name);
writer.WriteString(" ");
writer.WriteKeyword("As");
writer.WriteString(" ");
string typeName = (string) type.Evaluate(apiNameExpression);
if (reservedWords.ContainsKey(typeName)) {
writer.WriteString("[");
WriteTypeReference(type, writer);
writer.WriteString("]");
} else {
WriteTypeReference(type, writer);
}
writer.WriteLine();
}
public override void WriteClassSyntax (XPathNavigator reflection, SyntaxWriter writer) {
bool isAbstract = (bool)reflection.Evaluate(apiIsAbstractTypeExpression);
bool isSealed = (bool)reflection.Evaluate(apiIsSealedTypeExpression);
if (isAbstract && isSealed) {
writer.WriteMessage("UnsupportedStaticClass_" + Language);
} else {
TypeDeclaration(reflection, writer);
}
}
public override void WriteStructureSyntax (XPathNavigator reflection, SyntaxWriter writer) {
TypeDeclaration(reflection, writer);
}
public override void WriteInterfaceSyntax (XPathNavigator reflection, SyntaxWriter writer) {
TypeDeclaration(reflection, writer, true); // Need to write variance info for interfaces and delegates
}
public override void WriteDelegateSyntax (XPathNavigator reflection, SyntaxWriter writer) {
if (IsUnsupportedUnsafe(reflection, writer)) return;
string name = (string)reflection.Evaluate(apiNameExpression);
writer.WriteKeyword("Dim");
writer.WriteString(" ");
writer.WriteParameter("instance");
writer.WriteString(" ");
writer.WriteKeyword("As");
writer.WriteString(" ");
writer.WriteKeyword("New");
writer.WriteString(" ");
if (reservedWords.ContainsKey(name)) {
writer.WriteString("[");
writer.WriteIdentifier(name);
writer.WriteString("]");
} else {
writer.WriteIdentifier(name);
}
WriteGenericTemplates(reflection, writer, true); // Need to write variance info for interfaces and delegates
writer.WriteString("(");
writer.WriteKeyword("AddressOf");
writer.WriteString(" HandlerMethod)");
}
public override void WriteEnumerationSyntax (XPathNavigator reflection, SyntaxWriter writer) {
TypeDeclaration(reflection, writer);
}
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 isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
XPathNavigator fieldType = reflection.SelectSingleNode(apiReturnTypeExpression);
if (!(isStatic || isFamily)) ParameterDeclaration("instance", declaringType, writer);
ParameterDeclaration("value", fieldType, writer);
// get value
writer.WriteLine();
writer.WriteParameter("value");
writer.WriteString(" = ");
if (isStatic) {
WriteTypeReference(declaringType, writer);
} else {
if (isFamily) {
writer.WriteKeyword("Me");
} else {
writer.WriteParameter("instance");
}
}
writer.WriteString(".");
writer.WriteIdentifier(name);
writer.WriteLine();
// set value
if (isLiteral || isInitOnly) return;
writer.WriteLine();
if (isStatic) {
WriteTypeReference(declaringType, writer);
} else {
if (isFamily) {
writer.WriteKeyword("Me");
} else {
writer.WriteParameter("instance");
}
}
writer.WriteString(".");
writer.WriteIdentifier(name);
writer.WriteString(" = ");
writer.WriteParameter("value");
}
public override void WriteConstructorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
if (IsUnsupportedUnsafe(reflection, writer)) return;
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
// if static, no usage
WriteParameterDeclarations(reflection, writer);
writer.WriteLine();
writer.WriteKeyword("Dim");
writer.WriteString(" ");
writer.WriteParameter("instance");
writer.WriteString(" ");
writer.WriteKeyword("As New");
writer.WriteString(" ");
string typeName = (string)declaringType.Evaluate(apiNameExpression);
if (reservedWords.ContainsKey(typeName)) {
writer.WriteString("[");
WriteTypeReference(declaringType, writer);
writer.WriteString("]");
} else {
WriteTypeReference(declaringType, writer);
}
WriteMethodParameters(reflection, writer);
}
public override void WriteMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
if (IsUnsupportedUnsafe(reflection, writer)) return;
base.WriteMethodSyntax(reflection, writer);
}
public override void WriteNormalMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
bool isExtension = (bool)reflection.Evaluate(apiIsExtensionMethod);
if (isExtension) {
WriteExtensionMethodSyntax(reflection, writer);
} else {
//string name = (string)reflection.Evaluate(apiNameExpression);
XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
//bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
if (!(isStatic || isFamily)) ParameterDeclaration("instance", declaringType, writer);
WriteParameterDeclarations(reflection, writer);
if (returnType != null) ParameterDeclaration("returnValue", returnType, writer);
writer.WriteLine();
if (returnType != null) {
writer.WriteParameter("returnValue");
writer.WriteString(" = ");
}
WriteMemberName(reflection, writer);
WriteMethodParameters(reflection, writer);
}
}
// what about generic methods?
private void WriteMemberName (XPathNavigator reflection, SyntaxWriter writer) {
string name = (string)reflection.Evaluate(apiNameExpression);
bool isExplicit = (bool)reflection.Evaluate(apiIsExplicitImplementationExpression);
bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
bool isDefault = (bool)reflection.Evaluate(apiIsDefaultMemberExpression);
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
if (isExplicit) {
XPathNavigator member = reflection.SelectSingleNode(apiImplementedMembersExpression);
XPathNavigator contract = member.SelectSingleNode(memberDeclaringTypeExpression);
writer.WriteKeyword("CType");
writer.WriteString("(");
writer.WriteParameter("instance");
writer.WriteString(", ");
WriteTypeReference(contract, writer);
writer.WriteString(").");
WriteMemberReference(member, writer);
} else {
if (isStatic) {
WriteTypeReference(declaringType, writer);
} else {
if (isFamily) {
writer.WriteKeyword("Me");
} else {
writer.WriteString("instance");
}
}
if (!isDefault) {
writer.WriteString(".");
writer.WriteIdentifier(name);
}
}
}
private void WriteExtensionMethodSyntax (XPathNavigator reflection, SyntaxWriter writer) {
string name = (string)reflection.Evaluate(apiNameExpression);
XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
// extract the first parameter as the extension type
parameters.MoveNext();
XPathNavigator extendedType = parameters.Current.SelectSingleNode(parameterTypeExpression);
string extendedTypeName = (string) parameters.Current.Evaluate(parameterNameExpression);
// write the declarations
ParameterDeclaration(extendedTypeName, extendedType, writer);
WriteParameterDeclarations(parameters.Clone(), writer);
if (returnType != null) ParameterDeclaration("returnValue", returnType, writer);
writer.WriteLine();
// write the method invocation
if (returnType != null) {
writer.WriteParameter("returnValue");
writer.WriteString(" = ");
}
writer.WriteParameter(extendedTypeName);
writer.WriteString(".");
writer.WriteIdentifier(name);
writer.WriteString("(");
WriteParameters(parameters.Clone(), reflection, writer);
writer.WriteString(")");
}
public override void WriteOperatorSyntax (XPathNavigator reflection, SyntaxWriter writer) {
string name = (string) reflection.Evaluate(apiNameExpression);
XPathNavigator returnType = reflection.SelectSingleNode(apiReturnTypeExpression);
// Determine operator identifier and type
string identifier;
int type;
switch (name) {
// unary math operators
case "UnaryPlus":
identifier = "+";
type = -1;
break;
case "UnaryNegation":
identifier = "-";
type = -1;
break;
case "Increment":
identifier = "++";
type = +1;
break;
case "Decrement":
identifier = "--";
type = +1;
break;
// unary logical operators
case "LogicalNot":
identifier = "Not";
type = -1;
break;
case "True":
identifier = "IsTrue";
type = -1;
break;
case "False":
identifier = "IsFalse";
type = -1;
break;
// binary comparison operators
case "Equality":
identifier = "=";
type = 2;
break;
case "Inequality":
identifier = "<>";
type = 2;
break;
case "LessThan":
identifier = "<";
type = 2;
break;
case "GreaterThan":
identifier = ">";
type = 2;
break;
case "LessThanOrEqual":
identifier = "<=";
type = 2;
break;
case "GreaterThanOrEqual":
identifier = ">=";
type = 2;
break;
// binary math operators
case "Addition":
identifier = "+";
type = 2;
break;
case "Subtraction":
identifier = "-";
type = 2;
break;
case "Multiply":
identifier = "*";
type = 2;
break;
case "Division":
identifier = "/";
type = 2;
break;
case "Exponent":
identifier = "^";
type = 2;
break;
case "Modulus":
identifier = "Mod";
type = 2;
break;
case "IntegerDivision":
identifier = @"\";
type = 2;
break;
// binary logical operators
case "BitwiseAnd":
identifier = "And";
type = 2;
break;
case "BitwiseOr":
identifier = "Or";
type = 2;
break;
case "ExclusiveOr":
identifier = "Xor";
type = 2;
break;
// bit-array operators
case "OnesComplement":
identifier = "~";
type = -1;
break;
case "LeftShift":
identifier = "<<";
type = 2;
break;
case "RightShift":
identifier = ">>";
type = 2;
break;
// concatenation
case "Concatenate":
identifier = "&";
type = 2;
break;
// didn't recognize an operator
default:
identifier = null;
type = 0;
break;
}
if (identifier == null) {
writer.WriteMessage("UnsupportedOperator_" + Language);
} else {
XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
if (parameters.Count != Math.Abs(type)) {
writer.WriteMessage("UnsupportedOperator_" + Language);
return;
} //throw new InvalidOperationException("An operator has the wrong number of parameters.");
WriteParameterDeclarations(reflection, writer);
ParameterDeclaration("returnValue", returnType, writer);
writer.WriteLine();
writer.WriteParameter("returnValue");
writer.WriteString(" = ");
switch (type) {
case -1:
writer.WriteIdentifier(identifier);
parameters.MoveNext();
writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
break;
case +1:
parameters.MoveNext();
writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
writer.WriteIdentifier(identifier);
break;
case 2:
writer.WriteString("(");
// parameter 1
parameters.MoveNext();
writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
writer.WriteString(" ");
writer.WriteIdentifier(identifier);
writer.WriteString(" ");
// parameter 2
parameters.MoveNext();
writer.WriteParameter((string)parameters.Current.Evaluate(parameterNameExpression));
writer.WriteString(")");
break;
}
}
}
public override void WriteCastSyntax (XPathNavigator reflection, SyntaxWriter writer) {
XPathNavigator parameter = reflection.SelectSingleNode(apiParametersExpression);
if (parameter == null) return;
XPathNavigator inputType = parameter.SelectSingleNode(typeExpression);
XPathNavigator outputType = reflection.SelectSingleNode(apiReturnTypeExpression);
if ((inputType == null) || (outputType == null)) return;
ParameterDeclaration("input", inputType, writer);
ParameterDeclaration("output", outputType, writer);
writer.WriteLine();
writer.WriteParameter("output");
writer.WriteString(" = ");
writer.WriteKeyword("CType");
writer.WriteString("(");
writer.WriteParameter("input");
writer.WriteString(", ");
WriteTypeReference(outputType, writer);
writer.WriteString(")");
}
public override void WritePropertySyntax (XPathNavigator reflection, SyntaxWriter writer) {
if (IsUnsupportedUnsafe(reflection, writer)) return;
bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
XPathNavigator propertyType = reflection.SelectSingleNode(apiReturnTypeExpression);
bool getter = (bool)reflection.Evaluate(apiIsReadPropertyExpression);
bool setter = (bool)reflection.Evaluate(apiIsWritePropertyExpression);
if (!(isStatic || isFamily)) ParameterDeclaration("instance", declaringType, writer);
WriteParameterDeclarations(reflection, writer);
ParameterDeclaration("value", propertyType, writer);
// get value
if (getter) {
string getVisibility = (string)reflection.Evaluate(apiGetVisibilityExpression);
if (string.IsNullOrEmpty(getVisibility) || (getVisibility != "assembly" &&
getVisibility != "private" && getVisibility != "family and assembly"))
{
writer.WriteLine();
writer.WriteParameter("value");
writer.WriteString(" = ");
WriteMemberName(reflection, writer);
WritePropertyParameters(reflection, writer);
writer.WriteLine();
}
}
// set value
if (setter) {
string setVisibility = (string)reflection.Evaluate(apiSetVisibilityExpression);
if (string.IsNullOrEmpty(setVisibility) || (setVisibility != "assembly" &&
setVisibility != "private" && setVisibility != "family and assembly"))
{
writer.WriteLine();
WriteMemberName(reflection, writer);
WritePropertyParameters(reflection, writer);
writer.WriteString(" = ");
writer.WriteParameter("value");
}
}
}
public override void WriteEventSyntax (XPathNavigator reflection, SyntaxWriter writer) {
bool isStatic = (bool)reflection.Evaluate(apiIsStaticExpression);
bool isFamily = (bool)reflection.Evaluate(apiIsFamilyMemberExpression);
XPathNavigator declaringType = reflection.SelectSingleNode(apiContainingTypeExpression);
XPathNavigator handler = reflection.SelectSingleNode(apiHandlerOfEventExpression);
if (!(isStatic | isFamily)) ParameterDeclaration("instance", declaringType, writer);
ParameterDeclaration("handler", handler, writer);
// adder
writer.WriteLine();
writer.WriteKeyword("AddHandler");
writer.WriteString(" ");
WriteMemberName(reflection, writer);
writer.WriteString(", ");
writer.WriteParameter("handler");
writer.WriteLine();
}
private void WriteParameterDeclarations (XPathNavigator reflection, SyntaxWriter writer) {
XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
if (parameters.Count == 0) return;
WriteParameterDeclarations(parameters, writer);
}
private void WriteParameterDeclarations (XPathNodeIterator parameters, SyntaxWriter writer) {
while (parameters.MoveNext()) {
XPathNavigator parameter = parameters.Current;
XPathNavigator type = parameter.SelectSingleNode(parameterTypeExpression);
string name = (string)parameter.Evaluate(parameterNameExpression);
ParameterDeclaration(name, type, writer);
}
}
private void WriteMethodParameters (XPathNavigator reflection, SyntaxWriter writer) {
XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
writer.WriteString("(");
if (parameters.Count > 0) {
WriteParameters(parameters, reflection, writer);
}
writer.WriteString(")");
}
private void WritePropertyParameters (XPathNavigator reflection, SyntaxWriter writer) {
XPathNodeIterator parameters = reflection.Select(apiParametersExpression);
if (parameters.Count == 0) return;
writer.WriteString("(");
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);
writer.WriteParameter(name);
if (parameters.CurrentPosition < parameters.Count)
{
writer.WriteString(", ");
if (writer.Position > maxPosition)
{
writer.WriteString("_");
writer.WriteLine();
writer.WriteString("\t");
}
}
}
}
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("(");
writer.WriteKeyword("Of");
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 reference, SyntaxWriter writer) {
switch (reference) {
case "T:System.Int16":
writer.WriteReferenceLink(reference, "Short");
break;
case "T:System.Int32":
writer.WriteReferenceLink(reference, "Integer");
break;
case "T:System.Int64":
writer.WriteReferenceLink(reference, "Long");
break;
case "T:System.UInt16":
writer.WriteReferenceLink(reference, "UShort");
break;
case "T:System.UInt32":
writer.WriteReferenceLink(reference, "UInteger");
break;
case "T:System.UInt64":
writer.WriteReferenceLink(reference, "ULong");
break;
default:
writer.WriteReferenceLink(reference);
break;
}
}
private void WriteMemberReference (XPathNavigator member, SyntaxWriter writer) {
string api = member.GetAttribute("api", String.Empty);
writer.WriteReferenceLink(api);
}
private static Dictionary<string, object> reservedWords = new Dictionary<string, object>();
static VisualBasicUsageSyntaxGenerator () {
reservedWords.Add("Alias", null);
reservedWords.Add("Assembly", null);
reservedWords.Add("Class", null);
reservedWords.Add("Delegate", null);
reservedWords.Add("Function", null);
reservedWords.Add("Handles", null);
reservedWords.Add("Interface", null);
reservedWords.Add("Loop", null);
reservedWords.Add("Module", null);
reservedWords.Add("New", null);
reservedWords.Add("Next", null);
reservedWords.Add("Nothing", null);
reservedWords.Add("Operator", null);
reservedWords.Add("Option", null);
reservedWords.Add("Property", null);
reservedWords.Add("Structure", null);
}
}
}
|