📄 codedomvisitor.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision: 1323 $</version>
// </file>
using System;
using System.Collections;
using System.CodeDom;
using System.Text;
using Boo.Lang.Compiler;
using Boo.Lang.Compiler.Ast;
using Boo.Lang.Compiler.Ast.Visitors;
using Boo.Lang.Parser;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using Grunwald.BooBinding.CodeCompletion;
namespace Grunwald.BooBinding.Designer
{
/// <summary>
/// The CodeDomVisitor is able to convert from the Boo AST to System.CodeDom
/// It makes use of the SharpDevelop parser service to get necessary additional
/// information about the types.
/// </summary>
public class CodeDomVisitor : DepthFirstVisitor
{
CodeCompileUnit _compileUnit = new CodeCompileUnit();
public CodeCompileUnit OutputCompileUnit {
get {
return _compileUnit;
}
}
IProjectContent pc;
public CodeDomVisitor(IProjectContent pc)
{
this.pc = pc;
}
CodeNamespace _namespace;
CodeTypeDeclaration _class;
CodeStatementCollection _statements;
CodeExpression _expression;
MemberAttributes ConvModifiers(TypeMember member)
{
if (member is Field)
return ConvModifiers(member.Modifiers, MemberAttributes.Family);
else
return ConvModifiers(member.Modifiers, MemberAttributes.Public);
}
MemberAttributes ConvModifiers(TypeMemberModifiers modifier, MemberAttributes defaultAttr)
{
MemberAttributes attr = 0;
if ((modifier & TypeMemberModifiers.Abstract) == TypeMemberModifiers.Abstract)
attr |= MemberAttributes.Abstract;
if ((modifier & TypeMemberModifiers.Final) == TypeMemberModifiers.Final)
attr |= MemberAttributes.Const;
if ((modifier & TypeMemberModifiers.Internal) == TypeMemberModifiers.Internal)
attr |= MemberAttributes.Assembly;
if ((modifier & TypeMemberModifiers.Override) == TypeMemberModifiers.Override)
attr |= MemberAttributes.Override;
if ((modifier & TypeMemberModifiers.Private) == TypeMemberModifiers.Private)
attr |= MemberAttributes.Private;
if ((modifier & TypeMemberModifiers.Protected) == TypeMemberModifiers.Protected)
attr |= MemberAttributes.Family;
if ((modifier & TypeMemberModifiers.Public) == TypeMemberModifiers.Public)
attr |= MemberAttributes.Public;
if ((modifier & TypeMemberModifiers.Static) == TypeMemberModifiers.Static)
attr |= MemberAttributes.Static;
if ((modifier & TypeMemberModifiers.Virtual) != TypeMemberModifiers.Virtual)
attr |= MemberAttributes.Final;
if (attr == 0)
return defaultAttr;
else
return attr;
}
CodeTypeReference ConvTypeRef(TypeReference tr)
{
if (tr == null) return null;
string name = tr.ToString();
if (BooAmbience.ReverseTypeConversionTable.ContainsKey(name))
name = BooAmbience.ReverseTypeConversionTable[name];
return new CodeTypeReference(name);
}
public override void OnCompileUnit(CompileUnit node)
{
foreach (Module m in node.Modules)
m.Accept(this);
}
public override void OnModule(Module node)
{
if (node.Namespace == null) {
_namespace = new CodeNamespace("Global");
_compileUnit.Namespaces.Add(_namespace);
} else {
node.Namespace.Accept(this);
}
foreach (Import i in node.Imports)
i.Accept(this);
foreach (TypeMember m in node.Members)
m.Accept(this);
}
public override void OnNamespaceDeclaration(NamespaceDeclaration node)
{
_namespace = new CodeNamespace(node.Name);
_compileUnit.Namespaces.Add(_namespace);
}
public override void OnImport(Import node)
{
_namespace.Imports.Add(new CodeNamespaceImport(node.Namespace));
}
CodeTypeDeclaration ConvertTypeDefinition(TypeDefinition node)
{
CodeTypeDeclaration oldClass = _class;
CodeTypeDeclaration newClass = new CodeTypeDeclaration(node.Name);
_class = newClass;
foreach (TypeReference b in node.BaseTypes)
newClass.BaseTypes.Add(ConvTypeRef(b));
foreach (TypeMember member in node.Members)
member.Accept(this);
if (oldClass == null)
_namespace.Types.Add(newClass);
else
oldClass.Members.Add(newClass);
_class = oldClass;
return newClass;
}
public override void OnClassDefinition(ClassDefinition node)
{
ConvertTypeDefinition(node).IsClass = true;
}
public override void OnStructDefinition(StructDefinition node)
{
ConvertTypeDefinition(node).IsStruct = true;
}
public override void OnInterfaceDefinition(InterfaceDefinition node)
{
ConvertTypeDefinition(node).IsInterface = true;
}
public override void OnField(Field node)
{
CodeMemberField field = new CodeMemberField(ConvTypeRef(node.Type), node.Name);
field.Attributes = ConvModifiers(node);
if (node.Initializer != null) {
_expression = null;
//Visit(node.Initializer);
field.InitExpression = _expression;
}
_class.Members.Add(field);
}
public override void OnConstructor(Boo.Lang.Compiler.Ast.Constructor node)
{
ConvertMethod(node, new CodeConstructor());
}
public override void OnMethod(Method node)
{
CodeMemberMethod cmm = new CodeMemberMethod();
cmm.Name = node.Name;
cmm.ReturnType = ConvTypeRef(node.ReturnType);
ConvertMethod(node, cmm);
}
public override void OnDestructor(Boo.Lang.Compiler.Ast.Destructor node)
{
CodeMemberMethod cmm = new CodeMemberMethod();
cmm.Name = "Finalize";
ConvertMethod(node, cmm);
}
void ConvertMethod(Method node, CodeMemberMethod method)
{
method.Attributes = ConvModifiers(node);
if (node.Parameters != null) {
foreach (ParameterDeclaration p in node.Parameters)
method.Parameters.Add(new CodeParameterDeclarationExpression(ConvTypeRef(p.Type), p.Name));
}
_statements = method.Statements;
if (node.Body != null)
node.Body.Accept(this);
_class.Members.Add(method);
}
static CodeBinaryOperatorType GetOperatorType(BinaryOperatorType op)
{
switch (op) {
case BinaryOperatorType.Addition:
return CodeBinaryOperatorType.Add;
case BinaryOperatorType.And:
return CodeBinaryOperatorType.BooleanAnd;
case BinaryOperatorType.BitwiseAnd:
return CodeBinaryOperatorType.BitwiseAnd;
case BinaryOperatorType.BitwiseOr:
return CodeBinaryOperatorType.BitwiseOr;
case BinaryOperatorType.Division:
return CodeBinaryOperatorType.Divide;
case BinaryOperatorType.Equality:
return CodeBinaryOperatorType.ValueEquality;
case BinaryOperatorType.GreaterThan:
return CodeBinaryOperatorType.GreaterThan;
case BinaryOperatorType.GreaterThanOrEqual:
return CodeBinaryOperatorType.GreaterThanOrEqual;
case BinaryOperatorType.LessThan:
return CodeBinaryOperatorType.LessThan;
case BinaryOperatorType.LessThanOrEqual:
return CodeBinaryOperatorType.LessThanOrEqual;
case BinaryOperatorType.Modulus:
return CodeBinaryOperatorType.Modulus;
case BinaryOperatorType.Multiply:
return CodeBinaryOperatorType.Multiply;
case BinaryOperatorType.Or:
return CodeBinaryOperatorType.BooleanOr;
case BinaryOperatorType.Subtraction:
return CodeBinaryOperatorType.Subtract;
default:
return CodeBinaryOperatorType.Assign;
}
}
public override void OnBinaryExpression(BinaryExpression node)
{
_expression = null;
CodeBinaryOperatorType op = GetOperatorType(node.Operator);
if (op == CodeBinaryOperatorType.Assign) {
// non-standard op
if (node.Operator == BinaryOperatorType.Assign) {
node.Left.Accept(this);
CodeExpression left = _expression;
_expression = null;
node.Right.Accept(this);
if (left != null && _expression != null)
_statements.Add(new CodeAssignStatement(left, _expression));
_expression = null;
} else if (node.Operator == BinaryOperatorType.InPlaceAddition) {
node.Left.Accept(this);
CodeEventReferenceExpression left = _expression as CodeEventReferenceExpression;
_expression = null;
node.Right.Accept(this);
if (left != null && _expression != null)
_statements.Add(new CodeAttachEventStatement(left, _expression));
_expression = null;
} else {
LoggingService.Warn("CodeDomVisitor: ignoring unknown Binary Operator" + node.Operator);
}
} else {
node.Left.Accept(this);
CodeExpression left = _expression;
_expression = null;
node.Right.Accept(this);
_expression = new CodeBinaryOperatorExpression(left, op, _expression);
}
}
public override void OnTryCastExpression(TryCastExpression node)
{
_expression = null;
node.Target.Accept(this);
if (_expression == null)
return;
if (_expression is CodeMethodReferenceExpression) {
_expression = new CodeObjectCreateExpression(ConvTypeRef(node.Type), _expression);
} else {
_expression = new CodeCastExpression(ConvTypeRef(node.Type), _expression);
}
}
public override void OnCastExpression(CastExpression node)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -