364 lines
13 KiB
C#
364 lines
13 KiB
C#
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: TokenDefinition.cs
|
||
|
//
|
||
|
// Note: Declares a class describing MetaData tokens, so that the
|
||
|
// metadata parser's consts can all be easily identified.
|
||
|
using System;
|
||
|
using System.Diagnostics;
|
||
|
using System.Xml;
|
||
|
using Bartok.MSIL;
|
||
|
|
||
|
public class TokenDefinition
|
||
|
{
|
||
|
// name of the metadata attribute to match
|
||
|
public readonly string attribute;
|
||
|
|
||
|
// name of the xml tag to output
|
||
|
public readonly string xmlTagName;
|
||
|
|
||
|
// labels for constructor fields during output
|
||
|
public readonly string [] constructorFields;
|
||
|
|
||
|
// labels for properties to be renamed during output
|
||
|
// each property uses two addresses [default, new name]
|
||
|
public readonly string [] propertyReplacements;
|
||
|
|
||
|
// fields to be added with default values, if not named
|
||
|
public readonly string [] defaultFields;
|
||
|
|
||
|
// basic constructor; everything is public, but now it's all very easy to
|
||
|
// keep track of.
|
||
|
public TokenDefinition(string xmlTagName,
|
||
|
string attribute,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements,
|
||
|
string [] defaultFields)
|
||
|
{
|
||
|
this.xmlTagName = xmlTagName;
|
||
|
this.attribute = attribute;
|
||
|
this.constructorFields = constructorFields;
|
||
|
if (propertyReplacements != null && (propertyReplacements.Length % 2) != 0) {
|
||
|
Console.WriteLine("{0} has bad propertyReplacements", xmlTagName);
|
||
|
}
|
||
|
this.propertyReplacements = propertyReplacements;
|
||
|
if (defaultFields != null && (defaultFields.Length % 2) != 0) {
|
||
|
Console.WriteLine("{0} has bad defaultFields", xmlTagName);
|
||
|
}
|
||
|
this.defaultFields = defaultFields;
|
||
|
}
|
||
|
|
||
|
public TokenDefinition(string xmlTagName,
|
||
|
string attribute,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements)
|
||
|
: this(xmlTagName, attribute, constructorFields, propertyReplacements, new string[0])
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public TokenDefinition(string xmlTagName,
|
||
|
string attribute,
|
||
|
string [] constructorFields)
|
||
|
: this(xmlTagName, attribute, constructorFields, new string[0], new string[0])
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public TokenDefinition(string xmlTagName,
|
||
|
string attribute)
|
||
|
: this(xmlTagName, attribute, new string[0], new string[0], new string[0])
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public string FindPropertyReplacement(string name)
|
||
|
{
|
||
|
if (propertyReplacements != null) {
|
||
|
for (int pair = 0; pair < propertyReplacements.Length; pair += 2) {
|
||
|
if (propertyReplacements[pair] == name) {
|
||
|
return propertyReplacements[pair + 1];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return name;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class TriggerDefinition : TokenDefinition
|
||
|
{
|
||
|
// name of the category
|
||
|
public readonly string categoryName;
|
||
|
|
||
|
// name of the class that the decorated class must directly inherit from
|
||
|
public readonly string derivesFromClass;
|
||
|
|
||
|
public TriggerDefinition(string xmlTagName,
|
||
|
string categoryName,
|
||
|
string attribute,
|
||
|
string derivesFromClass,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements,
|
||
|
string [] defaultFields)
|
||
|
: base(xmlTagName,
|
||
|
attribute,
|
||
|
constructorFields,
|
||
|
propertyReplacements,
|
||
|
defaultFields)
|
||
|
{
|
||
|
this.derivesFromClass = derivesFromClass;
|
||
|
this.categoryName = categoryName;
|
||
|
}
|
||
|
|
||
|
public TriggerDefinition(string xmlTagName,
|
||
|
string categoryName,
|
||
|
string attribute,
|
||
|
string derivesFromClass,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements)
|
||
|
: base(xmlTagName, attribute, constructorFields, propertyReplacements, new string[0])
|
||
|
{
|
||
|
this.derivesFromClass = derivesFromClass;
|
||
|
this.categoryName = categoryName;
|
||
|
}
|
||
|
|
||
|
public TriggerDefinition(string xmlTagName,
|
||
|
string categoryName,
|
||
|
string attribute,
|
||
|
string derivesFromClass,
|
||
|
string [] constructorFields)
|
||
|
: base(xmlTagName, attribute, constructorFields, new string[0], new string[0])
|
||
|
{
|
||
|
this.derivesFromClass = derivesFromClass;
|
||
|
this.categoryName = categoryName;
|
||
|
}
|
||
|
|
||
|
public TriggerDefinition(string xmlTagName,
|
||
|
string categoryName,
|
||
|
string attribute,
|
||
|
string derivesFromClass)
|
||
|
: base(xmlTagName, attribute, new string[0], new string[0], new string[0])
|
||
|
{
|
||
|
this.derivesFromClass = derivesFromClass;
|
||
|
this.categoryName = categoryName;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class ClassDefinition : TokenDefinition
|
||
|
{
|
||
|
public ClassDefinition(string xmlTagName,
|
||
|
string attribute,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements,
|
||
|
string [] defaultFields)
|
||
|
: base(xmlTagName,
|
||
|
attribute,
|
||
|
constructorFields,
|
||
|
propertyReplacements,
|
||
|
defaultFields)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ClassDefinition(string xmlTagName,
|
||
|
string attribute,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements)
|
||
|
: base(xmlTagName, attribute, constructorFields, propertyReplacements, new string[0])
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ClassDefinition(string xmlTagName,
|
||
|
string attribute,
|
||
|
string [] constructorFields)
|
||
|
: base(xmlTagName, attribute, constructorFields, new string[0], new string[0])
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ClassDefinition(string xmlTagName,
|
||
|
string attribute)
|
||
|
: base(xmlTagName, attribute, new string[0], new string[0], new string[0])
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class ParameterDefinition : FieldDefinition
|
||
|
{
|
||
|
public ParameterDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType,
|
||
|
string [] constructorFields)
|
||
|
: base(xmlGroup,
|
||
|
xmlTagName,
|
||
|
attribute,
|
||
|
matchClassType,
|
||
|
constructorFields)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
}
|
||
|
public class FieldDefinition : TokenDefinition
|
||
|
{
|
||
|
// name of the group to put the field into.
|
||
|
public readonly string xmlGroup;
|
||
|
|
||
|
// name of the class that the decorated class must be (fields only)
|
||
|
public readonly string matchClassType;
|
||
|
|
||
|
public FieldDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements,
|
||
|
string [] defaultFields)
|
||
|
: base(xmlTagName,
|
||
|
attribute,
|
||
|
constructorFields,
|
||
|
propertyReplacements,
|
||
|
defaultFields)
|
||
|
{
|
||
|
this.xmlGroup = xmlGroup;
|
||
|
this.matchClassType = matchClassType;
|
||
|
}
|
||
|
|
||
|
public FieldDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType,
|
||
|
string [] constructorFields,
|
||
|
string [] propertyReplacements)
|
||
|
: base(xmlTagName,
|
||
|
attribute,
|
||
|
constructorFields,
|
||
|
propertyReplacements,
|
||
|
new string[0])
|
||
|
{
|
||
|
this.xmlGroup = xmlGroup;
|
||
|
this.matchClassType = matchClassType;
|
||
|
}
|
||
|
|
||
|
public FieldDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType,
|
||
|
string [] constructorFields)
|
||
|
: base(xmlTagName,
|
||
|
attribute,
|
||
|
constructorFields,
|
||
|
new string[0],
|
||
|
new string[0])
|
||
|
{
|
||
|
this.xmlGroup = xmlGroup;
|
||
|
this.matchClassType = matchClassType;
|
||
|
}
|
||
|
|
||
|
public FieldDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType)
|
||
|
: base(xmlTagName,
|
||
|
attribute,
|
||
|
new string[0],
|
||
|
new string[0],
|
||
|
new string[0])
|
||
|
{
|
||
|
this.xmlGroup = xmlGroup;
|
||
|
this.matchClassType = matchClassType;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class EndpointDefinition : FieldDefinition
|
||
|
{
|
||
|
public EndpointDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType)
|
||
|
: base(xmlGroup,
|
||
|
xmlTagName,
|
||
|
attribute,
|
||
|
matchClassType,
|
||
|
new string[0],
|
||
|
new string[0],
|
||
|
new string[0])
|
||
|
{
|
||
|
}
|
||
|
public EndpointDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType,
|
||
|
string[] constructorFields)
|
||
|
: base(xmlGroup,
|
||
|
xmlTagName,
|
||
|
attribute,
|
||
|
matchClassType,
|
||
|
constructorFields,
|
||
|
new string[0],
|
||
|
new string[0])
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public virtual void AddContractNameAttribute(ManifestBuilder mfb,
|
||
|
XmlNode node,
|
||
|
MetaDataCustomAttribute data,
|
||
|
string contractName)
|
||
|
{
|
||
|
mfb.AddAttribute(node, "contractName", contractName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class ServiceEndpointDefinition : EndpointDefinition
|
||
|
{
|
||
|
public ServiceEndpointDefinition(string xmlGroup,
|
||
|
string xmlTagName,
|
||
|
string attribute,
|
||
|
string matchClassType)
|
||
|
: base(xmlGroup, xmlTagName, attribute, matchClassType)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public override void AddContractNameAttribute(ManifestBuilder mfb,
|
||
|
XmlNode node,
|
||
|
MetaDataCustomAttribute data,
|
||
|
string contractName)
|
||
|
{
|
||
|
// takes endpoint type as argument
|
||
|
if (data.FixedArgs == null || data.FixedArgs.Length != 1) {
|
||
|
mfb.Error("ServiceEndpoint attribute must have 1 type argument");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// now make it easy to split into name=value pairs by doing some
|
||
|
// string replacing
|
||
|
string ctorArgument = "contractName=" + data.FixedArgs[0];
|
||
|
ctorArgument = ctorArgument.Replace("+", " endpointEnd=");
|
||
|
ctorArgument = ctorArgument.Replace(", V", " v");
|
||
|
ctorArgument = ctorArgument.Replace(", C", " c");
|
||
|
ctorArgument = ctorArgument.Replace(", P", " p");
|
||
|
ctorArgument = ctorArgument.Replace(",", " assembly=");
|
||
|
|
||
|
// now we can split on ' ' and '=' to get name/value pairs
|
||
|
string [] endpointConfig = ctorArgument.Split(' ');
|
||
|
|
||
|
// grab only the contractName, ignore the rest
|
||
|
#if false
|
||
|
foreach (string attrib in endpointConfig) {
|
||
|
string [] pair = attrib.Split('=');
|
||
|
if (pair.Length == 2) {
|
||
|
string name = pair[0];
|
||
|
string value = pair[1];
|
||
|
AddAttribute(node, name, value);
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
string [] pair = endpointConfig[0].Split('=');
|
||
|
Debug.Assert(pair.Length == 2);
|
||
|
string name = pair[0];
|
||
|
Debug.Assert(name == "contractName");
|
||
|
string value = pair[1];
|
||
|
base.AddContractNameAttribute(mfb, node, data, value);
|
||
|
#endif
|
||
|
}
|
||
|
}
|