📄 nrefactoryastconvertvisitor.cs
字号:
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <version>$Revision: 1346 $</version>
// </file>
// created on 04.08.2003 at 17:49
using System;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using RefParser = ICSharpCode.NRefactory.Parser;
using AST = ICSharpCode.NRefactory.Parser.AST;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
public class NRefactoryASTConvertVisitor : RefParser.AbstractAstVisitor
{
ICompilationUnit cu;
Stack currentNamespace = new Stack();
Stack<DefaultClass> currentClass = new Stack<DefaultClass>();
public ICompilationUnit Cu {
get {
return cu;
}
}
public NRefactoryASTConvertVisitor(IProjectContent projectContent)
{
cu = new DefaultCompilationUnit(projectContent);
}
DefaultClass GetCurrentClass()
{
return currentClass.Count == 0 ? null : currentClass.Peek();
}
ModifierEnum ConvertModifier(AST.Modifier m)
{
if (currentClass.Count > 0 && currentClass.Peek().ClassType == ClassType.Interface)
return ConvertModifier(m, ModifierEnum.Public);
else
return ConvertModifier(m, ModifierEnum.Private);
}
ModifierEnum ConvertModifier(AST.Modifier m, ModifierEnum defaultModifier)
{
ModifierEnum r = (ModifierEnum)m;
if (r == ModifierEnum.None)
return defaultModifier;
else
return r;
}
List<RefParser.ISpecial> specials;
/// <summary>
/// Gets/Sets the list of specials used to read the documentation.
/// The list must be sorted by the start position of the specials!
/// </summary>
public List<RefParser.ISpecial> Specials {
get {
return specials;
}
set {
specials = value;
}
}
string GetDocumentation(int line, IList<AST.AttributeSection> attributes)
{
foreach (AST.AttributeSection att in attributes) {
if (att.StartLocation.Y > 0 && att.StartLocation.Y < line)
line = att.StartLocation.Y;
}
List<string> lines = new List<string>();
int length = 0;
while (line > 0) {
string doku = GetDocumentationFromLine(--line);
if (doku == null)
break;
length += 2 + doku.Length;
lines.Add(doku);
}
StringBuilder b = new StringBuilder(length);
for (int i = lines.Count - 1; i >= 0; --i) {
b.AppendLine(lines[i]);
}
return b.ToString();
}
string GetDocumentationFromLine(int line)
{
if (specials == null) return null;
if (line < 0) return null;
// specials is a sorted list: use interpolation search
int left = 0;
int right = specials.Count - 1;
int m;
while (left <= right) {
int leftLine = specials[left].StartPosition.Y;
if (line < leftLine)
break;
int rightLine = specials[right].StartPosition.Y;
if (line > rightLine)
break;
if (leftLine == rightLine) {
if (leftLine == line)
m = left;
else
break;
} else {
m = left + (line - leftLine) * (right - left) / (rightLine - leftLine);
}
int mLine = specials[m].StartPosition.Y;
if (mLine < line) { // found line smaller than line we are looking for
left = m + 1;
} else if (mLine > line) {
right = m - 1;
} else {
// correct line found,
// look for first special in that line
while (--m >= 0 && specials[m].StartPosition.Y == line);
// look at all specials in that line: find doku-comment
while (++m < specials.Count && specials[m].StartPosition.Y == line) {
RefParser.Comment comment = specials[m] as RefParser.Comment;
if (comment != null && comment.CommentType == RefParser.CommentType.Documentation) {
return comment.CommentText;
}
}
break;
}
}
return null;
}
public override object Visit(AST.CompilationUnit compilationUnit, object data)
{
if (compilationUnit == null) {
return null;
}
compilationUnit.AcceptChildren(this, data);
return cu;
}
public override object Visit(AST.UsingDeclaration usingDeclaration, object data)
{
DefaultUsing us = new DefaultUsing(cu.ProjectContent, GetRegion(usingDeclaration.StartLocation, usingDeclaration.EndLocation));
foreach (AST.Using u in usingDeclaration.Usings) {
u.AcceptVisitor(this, us);
}
cu.Usings.Add(us);
return data;
}
public override object Visit(AST.Using u, object data)
{
Debug.Assert(data is DefaultUsing);
DefaultUsing us = (DefaultUsing)data;
if (u.IsAlias) {
IReturnType rt = CreateReturnType(u.Alias);
if (rt != null) {
us.AddAlias(u.Name, rt);
}
} else {
us.Usings.Add(u.Name);
}
return data;
}
void ConvertAttributes(AST.AttributedNode from, AbstractDecoration to)
{
if (from.Attributes.Count == 0) {
to.Attributes = DefaultAttribute.EmptyAttributeList;
} else {
to.Attributes = VisitAttributes(from.Attributes);
}
}
List<IAttribute> VisitAttributes(List<AST.AttributeSection> attributes)
{
// TODO Expressions???
List<IAttribute> result = new List<IAttribute>();
foreach (AST.AttributeSection section in attributes) {
AttributeTarget target = AttributeTarget.None;
if (section.AttributeTarget != null && section.AttributeTarget != "") {
switch (section.AttributeTarget.ToUpperInvariant()) {
case "ASSEMBLY":
target = AttributeTarget.Assembly;
break;
case "FIELD":
target = AttributeTarget.Field;
break;
case "EVENT":
target = AttributeTarget.Event;
break;
case "METHOD":
target = AttributeTarget.Method;
break;
case "MODULE":
target = AttributeTarget.Module;
break;
case "PARAM":
target = AttributeTarget.Param;
break;
case "PROPERTY":
target = AttributeTarget.Property;
break;
case "RETURN":
target = AttributeTarget.Return;
break;
case "TYPE":
target = AttributeTarget.Type;
break;
default:
target = AttributeTarget.None;
break;
}
}
foreach (AST.Attribute attribute in section.Attributes) {
//IAttribute a = new DefaultAttribute(attribute.Name, target, new ArrayList(attribute.PositionalArguments), new SortedList());
//foreach (AST.NamedArgumentExpression n in attribute.NamedArguments) {
// a.NamedArguments[n.Name] = n.Expression;
//}
result.Add(new DefaultAttribute(attribute.Name, target));
}
}
return result;
}
public override object Visit(AST.NamespaceDeclaration namespaceDeclaration, object data)
{
string name;
if (currentNamespace.Count == 0) {
name = namespaceDeclaration.Name;
} else {
name = (string)currentNamespace.Peek() + '.' + namespaceDeclaration.Name;
}
currentNamespace.Push(name);
object ret = namespaceDeclaration.AcceptChildren(this, data);
currentNamespace.Pop();
return ret;
}
ClassType TranslateClassType(AST.ClassType type)
{
switch (type) {
case AST.ClassType.Enum:
return ClassType.Enum;
case AST.ClassType.Interface:
return ClassType.Interface;
case AST.ClassType.Struct:
return ClassType.Struct;
case AST.ClassType.Module:
return ClassType.Module;
default:
return ClassType.Class;
}
}
DomRegion GetRegion(Point start, Point end)
{
return new DomRegion(start, end);
}
public override object Visit(AST.TypeDeclaration typeDeclaration, object data)
{
DomRegion region = GetRegion(typeDeclaration.StartLocation, typeDeclaration.EndLocation);
DomRegion bodyRegion = GetRegion(typeDeclaration.BodyStartLocation, typeDeclaration.EndLocation);
DefaultClass c = new DefaultClass(cu, TranslateClassType(typeDeclaration.Type), ConvertModifier(typeDeclaration.Modifier, ModifierEnum.Internal), region, GetCurrentClass());
c.BodyRegion = bodyRegion;
ConvertAttributes(typeDeclaration, c);
c.Documentation = GetDocumentation(region.BeginLine, typeDeclaration.Attributes);
if (currentClass.Count > 0) {
DefaultClass cur = GetCurrentClass();
cur.InnerClasses.Add(c);
c.FullyQualifiedName = cur.FullyQualifiedName + '.' + typeDeclaration.Name;
} else {
if (currentNamespace.Count == 0) {
c.FullyQualifiedName = typeDeclaration.Name;
} else {
c.FullyQualifiedName = (string)currentNamespace.Peek() + '.' + typeDeclaration.Name;
}
cu.Classes.Add(c);
}
currentClass.Push(c);
if (c.ClassType != ClassType.Enum && typeDeclaration.BaseTypes != null) {
foreach (AST.TypeReference type in typeDeclaration.BaseTypes) {
IReturnType rt = CreateReturnType(type);
if (rt != null) {
c.BaseTypes.Add(rt);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -