📄 codedomoutputvisitor.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision: 1965 $</version>
// </file>
using System;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using ICSharpCode.NRefactory.Ast;
namespace ICSharpCode.NRefactory.Visitors
{
public class CodeDomVisitor : AbstractAstVisitor
{
Stack<CodeNamespace> namespaceDeclarations = new Stack<CodeNamespace>();
Stack<CodeTypeDeclaration> typeDeclarations = new Stack<CodeTypeDeclaration>();
Stack<CodeStatementCollection> codeStack = new Stack<CodeStatementCollection>();
List<CodeVariableDeclarationStatement> variables = new List<CodeVariableDeclarationStatement>();
List<CodeParameterDeclarationExpression> parameters = new List<CodeParameterDeclarationExpression>();
Stack<Breakable> breakableStack = new Stack<Breakable>();
TypeDeclaration currentTypeDeclaration = null;
IEnvironmentInformationProvider environmentInformationProvider = new DummyEnvironmentInformationProvider();
// track break and continue statements
class Breakable
{
public static int NextId = 0;
public int Id = 0;
public bool IsBreak = false;
public bool IsContinue = false;
public bool AllowContinue = true;
public Breakable()
{
Id = ++NextId;
}
public Breakable(bool allowContinue)
: this()
{
AllowContinue = allowContinue;
}
}
public IEnvironmentInformationProvider EnvironmentInformationProvider {
get {
return environmentInformationProvider;
}
set {
environmentInformationProvider = value;
}
}
// dummy collection used to swallow statements
CodeStatementCollection NullStmtCollection = new CodeStatementCollection();
public CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
// RG
//
// Initialise Scope Variables for Current Method
void InitMethodScope()
{
usingId = 0;
foreachId = 0;
switchId = 0;
doId = 0;
Breakable.NextId = 0;
variables.Clear();
parameters.Clear();
}
CodeTypeReference ConvType(TypeReference type)
{
if (type == null) {
throw new ArgumentNullException("type");
}
if (string.IsNullOrEmpty(type.SystemType)) {
throw new InvalidOperationException("empty type");
}
CodeTypeReference t = new CodeTypeReference(type.SystemType);
foreach (TypeReference gt in type.GenericTypes) {
t.TypeArguments.Add(ConvType(gt));
}
if (type.IsArrayType) {
t = new CodeTypeReference(t, type.RankSpecifier.Length);
}
return t;
}
void AddStmt(CodeStatement stmt)
{
if (codeStack.Count == 0)
return;
CodeStatementCollection stmtCollection = codeStack.Peek();
if (stmtCollection != null) {
stmtCollection.Add(stmt);
}
}
// FIXME: map all modifiers correctly
static MemberAttributes ConvMemberAttributes(Modifiers modifier)
{
MemberAttributes attr = (MemberAttributes)0;
if ((modifier & Modifiers.Abstract) != 0)
attr |= MemberAttributes.Abstract;
if ((modifier & Modifiers.Const) != 0)
attr |= MemberAttributes.Const;
if ((modifier & Modifiers.Sealed) != 0)
attr |= MemberAttributes.Final;
if ((modifier & Modifiers.New) != 0)
attr |= MemberAttributes.New;
if ((modifier & Modifiers.Virtual) != 0)
attr |= MemberAttributes.Overloaded;
if ((modifier & Modifiers.Override) != 0)
attr |= MemberAttributes.Override;
if ((modifier & Modifiers.Static) != 0)
attr |= MemberAttributes.Static;
if ((modifier & Modifiers.Public) != 0)
attr |= MemberAttributes.Public;
else if ((modifier & Modifiers.Internal) != 0 && (modifier & Modifiers.Protected) != 0)
attr |= MemberAttributes.FamilyOrAssembly;
else if ((modifier & Modifiers.Internal) != 0)
attr |= MemberAttributes.Assembly;
else if ((modifier & Modifiers.Protected) != 0)
attr |= MemberAttributes.Family;
else if ((modifier & Modifiers.Private) != 0)
attr |= MemberAttributes.Private;
return attr;
}
#region ICSharpCode.SharpRefactory.Parser.IASTVisitor interface implementation
public override object VisitCompilationUnit(CompilationUnit compilationUnit, object data)
{
if (compilationUnit == null) {
throw new ArgumentNullException("compilationUnit");
}
CodeNamespace globalNamespace = new CodeNamespace("Global");
//namespaces.Add(globalNamespace);
namespaceDeclarations.Push(globalNamespace);
compilationUnit.AcceptChildren(this, data);
codeCompileUnit.Namespaces.Add(globalNamespace);
return globalNamespace;
}
public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
{
CodeNamespace currentNamespace = new CodeNamespace(namespaceDeclaration.Name);
//namespaces.Add(currentNamespace);
// add imports from mother namespace
foreach (CodeNamespaceImport import in ((CodeNamespace)namespaceDeclarations.Peek()).Imports) {
currentNamespace.Imports.Add(import);
}
namespaceDeclarations.Push(currentNamespace);
namespaceDeclaration.AcceptChildren(this, data);
namespaceDeclarations.Pop();
codeCompileUnit.Namespaces.Add(currentNamespace);
// TODO : Nested namespaces allowed in CodeDOM ? Doesn't seem so :(
return null;
}
public override object VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data)
{
foreach (Using u in usingDeclaration.Usings) {
namespaceDeclarations.Peek().Imports.Add(new CodeNamespaceImport(u.Name));
}
return null;
}
// RG
public override object VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
{
CodeMemberEvent evt = new CodeMemberEvent();
evt.Type = ConvType(eventDeclaration.TypeReference);
evt.Name = eventDeclaration.Name;
evt.Attributes = ConvMemberAttributes(eventDeclaration.Modifier);
typeDeclarations.Peek().Members.Add(evt);
return null;
}
public override object VisitAttributeSection(AttributeSection attributeSection, object data)
{
return null;
}
// RG: CodeTypeReferenceExpression
public override object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
{
return new CodeTypeReferenceExpression(ConvType(typeReferenceExpression.TypeReference));
}
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{
TypeDeclaration oldTypeDeclaration = currentTypeDeclaration;
this.currentTypeDeclaration = typeDeclaration;
CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration(typeDeclaration.Name);
codeTypeDeclaration.IsClass = typeDeclaration.Type == ClassType.Class;
codeTypeDeclaration.IsEnum = typeDeclaration.Type == ClassType.Enum;
codeTypeDeclaration.IsInterface = typeDeclaration.Type == ClassType.Interface;
codeTypeDeclaration.IsStruct = typeDeclaration.Type == ClassType.Struct;
if (typeDeclaration.BaseTypes != null) {
foreach (TypeReference typeRef in typeDeclaration.BaseTypes) {
codeTypeDeclaration.BaseTypes.Add(ConvType(typeRef));
}
}
typeDeclarations.Push(codeTypeDeclaration);
typeDeclaration.AcceptChildren(this, data);
typeDeclarations.Pop();
if (typeDeclarations.Count > 0) {
typeDeclarations.Peek().Members.Add(codeTypeDeclaration);
} else {
namespaceDeclarations.Peek().Types.Add(codeTypeDeclaration);
}
currentTypeDeclaration = oldTypeDeclaration;
return null;
}
public override object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data)
{
CodeTypeDelegate codeTypeDelegate = new CodeTypeDelegate(delegateDeclaration.Name);
codeTypeDelegate.Attributes = ConvMemberAttributes(delegateDeclaration.Modifier);
codeTypeDelegate.ReturnType = ConvType(delegateDeclaration.ReturnType);
foreach (ParameterDeclarationExpression parameter in delegateDeclaration.Parameters)
{
codeTypeDelegate.Parameters.Add((CodeParameterDeclarationExpression)VisitParameterDeclarationExpression(parameter, data));
}
if (typeDeclarations.Count > 0)
{
typeDeclarations.Peek().Members.Add(codeTypeDelegate);
}
else
{
namespaceDeclarations.Peek().Types.Add(codeTypeDelegate);
}
return null;
}
public override object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data)
{
return null;
}
public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data)
{
for (int i = 0; i < fieldDeclaration.Fields.Count; ++i) {
VariableDeclaration field = (VariableDeclaration)fieldDeclaration.Fields[i];
if ((fieldDeclaration.Modifier & Modifiers.WithEvents) != 0) {
//this.withEventsFields.Add(field);
}
TypeReference fieldType = fieldDeclaration.GetTypeForField(i);
if (fieldType.IsNull) {
fieldType = new TypeReference(typeDeclarations.Peek().Name);
}
CodeMemberField memberField = new CodeMemberField(ConvType(fieldType), field.Name);
memberField.Attributes = ConvMemberAttributes(fieldDeclaration.Modifier);
if (!field.Initializer.IsNull) {
memberField.InitExpression = (CodeExpression)field.Initializer.AcceptVisitor(this, data);
}
typeDeclarations.Peek().Members.Add(memberField);
}
return null;
}
public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
{
InitMethodScope();
CodeMemberMethod memberMethod = new CodeMemberMethod();
memberMethod.Name = methodDeclaration.Name;
memberMethod.Attributes = ConvMemberAttributes(methodDeclaration.Modifier);
// RG: Private Interface Decl
if ((memberMethod.Attributes & MemberAttributes.Public) != MemberAttributes.Public &&
methodDeclaration.InterfaceImplementations.Count > 0)
{
memberMethod.PrivateImplementationType = ConvType(methodDeclaration.InterfaceImplementations[0].InterfaceType);
}
codeStack.Push(memberMethod.Statements);
typeDeclarations.Peek().Members.Add(memberMethod);
// Add Method Parameters
parameters.Clear();
foreach (ParameterDeclarationExpression parameter in methodDeclaration.Parameters)
{
memberMethod.Parameters.Add((CodeParameterDeclarationExpression)VisitParameterDeclarationExpression(parameter, data));
}
usingId = 0; // RG
foreachId = 0;
switchId = 0;
doId = 0;
Breakable.NextId = 0;
variables.Clear();
methodDeclaration.Body.AcceptChildren(this, data);
codeStack.Pop();
return null;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -