Parser及其应用: Code Completion, Method Insight, Class Scout ...
1、Demo界面及功能解释
2、Parser实现概述
3、Parser应用: MouseHover Tooltip
4、Parser应用: CodeCompletion & MethodInsight
5、Parser应用: QuickClassBrowserPanel
6、Parser应用: Folding
7、总结
Demo下载
1、Demo界面及功能解释
启动并打开任一 .cs 文件后,界面如下:
自动完成界面如下:
可见新增功能如下(仅支持.cs文件):
a, 鼠标停留在方法、属性等位置时,会显示出相关的文档描述tooltip
b, 输入时支持自动完成
c, 编辑窗口顶部有类列表和成员(方法、变量等)列表下拉框用以快速浏览、定位
d, 编辑窗口左侧有折叠线用以方法、类等的代码折叠
相应的Demo工程中新增项目如下:
a, SharpEditor: 包含扩展TextEditor的控件, Dom结构, ParserService, 自动完成功能代码等
b, NRefactor : 代码解析功能
c, CSharpBinding: 对应 .cs 文件的具体实现支持
[题外话]:
关于代码解析(Parser)相关的代码,我没看懂,所以在这里只说个大概,更多地谈谈Parser的使用;抛砖引玉,希望有相关经验的网友提供详尽的分析。
前两周工作上的项目实施,每天都搞得比较累,所以这篇文章到现在才写了出来,明天是大年三十了,这个系列的文章也只剩下一篇Windows Form Designer,只能等过了年再放上来喽。
另外,这个系列写完后,暂不打算深究一些没明白的细节,接下来想看下os workflow 或 CommunityServer...
2、Parser实现概述
(1)首先,SharpEditor项目中的Dom下定义了以下重要类:
a, IDecoration及其子类: 代码表现的辅助对象,如IClass, IMethod, IProperty等
b, ResolveResult及其子类: 分析结果对象,如MethodResolveResult, TypeResolveResult等
c, 其它重要类: IExpressionFinder, IParser, IResolve, ICompilationUnit 等
(2)重要服务类:
ParserService: 提供 GetExpressionFinder(), Resolve(), ParseFile()等重要方法,相关重要类: ProjectContentRegistry, DefaultProjectContent, ReflectionProjectContent等
AmbienceService: 提供 IAmbience的实现类用以将分析结果转换为相应的字符描述
(3)Parser分析步骤:
以鼠标悬浮的Tooltip显示为例:DebuggerService根据文件类型返回对应的IExpressionFinder实现类,再根据鼠标位置找到并返回ExpressionResult对象,然后找到适当的IResolver实现类调用Resolve()方法返回结果ResolveResult对象,最后由相应的IAmbience实现类转换成结果字符,并调用e.ShowToolTip(toolTipText);显示。
(4)对于.NET默认类库的分析转换:
默认引进的命名空间的类结构和文档说明一般可以在"C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/"目录下找到(如System.dll和System.xml),但是如果每次都要重新分析dll代码结构和xml注释显然是比较花费时间的,于是SharpDevelop采用的方式是将分析过的数据(Dom下的类结构表示数据?,二进制的.dat文件)存储到"C:/Documents and Settings/michael/Local Settings/Temp/SharpDevelop"下,代码结构存储到DomCacheDebug目录下,文档注释存储到DocumentationCacheDebug目录下。
首先在ParserService的CreateDefaultProjectContent()中加载默认命名空间的引用:
1
static void CreateDefaultProjectContent()2


{
3
LoggingService.Info("Creating default project content");4
LoggingService.Debug("Stacktrace is:/n" + Environment.StackTrace);5
defaultProjectContent = new DefaultProjectContent();6
defaultProjectContent.ReferencedContents.Add(ProjectContentRegistry.Mscorlib);7

string[] defaultReferences = new string[]
{
8
"System",9
"System.Data",10
"System.Drawing",11
"System.Windows.Forms",12
"System.XML",13
"Microsoft.VisualBasic",14
};15
foreach (string defaultReference in defaultReferences)16

{
17
//ReferenceProjectItem item = new ReferenceProjectItem(null, defaultReference);18
IProjectContent pc = ProjectContentRegistry.GetProjectContentForReference(defaultReference);19
if (pc != null)20

{
21
defaultProjectContent.ReferencedContents.Add(pc);22
}23
}24
}
其中ProjectContentRegistry的GetProjectContentForReference()方法如下:
1
public static IProjectContent GetProjectContentForReference(string Include)2


{
3
// 省略部分代码4
Assembly assembly = GetDefaultAssembly(shortName);5
ReflectionProjectContent pc;6
if (assembly != null)7

{
8
pc = DomPersistence.LoadProjectContentByAssemblyName(assembly.FullName);9
if (pc == null)10

{
11
pc = new ReflectionProjectContent(assembly);12
DomPersistence.SaveProjectContent(pc);13
}14
}15
else16

{
17
pc = LoadProjectContent(itemFileName, itemInclude);18
}19
// 省略部分代码20
return pc;21
}22
static Assembly GetDefaultAssembly(string shortName)23


{
24
// These assemblies are already loaded by SharpDevelop, so we don't need to load25
// them in a separate AppDomain.26

switch (shortName)
{
27
case "System": // System != mscorlib !!!28
return SystemAssembly;29
case "System.Data":30
return typeof(System.Data.DataException).Assembly;31
case "System.Design":32
return typeof(System.ComponentModel.Design.DesignSurface).Assembly;33
case "System.DirectoryServices":34
return typeof(System.DirectoryServices.AuthenticationTypes).Assembly;35
case "System.Drawing":36
return typeof(System.Drawing.Color).Assembly;37
case "System.Web.Services":38
return typeof(System.Web.Services.WebService).Assembly;39
case "System.Windows.Forms":40
return typeof(System.Windows.Forms.Control).Assembly;41
case "System.Xml":42
case "System.XML":43
return typeof(XmlReader).Assembly;44
case "Microsoft.Build.Engine":45
return typeof(Microsoft.Build.BuildEngine.BuildSettings).Assembly;46
case "Microsoft.Build.Framework":47
return typeof(Microsoft.Build.Framework.LoggerVerbosity).Assembly;48
default:49
return null;50
}51
}
可以看到DomPersistence类的作用即在加载或保存dll的代码结构数据, 如果尚未有分析过的数据,则在ReflectionProjectContnet类的构造函数中加以分析,同时调用XmlDoc类的相关方法加载、保存文档注释数据。
(5)对于文件的转换:
[略]
3、Parser应用: MouseHover Tooltip
注意在SharpEditor项目中有个DebuggerService类,它提供了一个重要方法如下:
1
public static void BindTextAreaEvent(TextEditorControl control)2


{
3
TextArea textArea = control.ActiveTextAreaControl.TextArea;4
//textArea.IconBarMargin.MouseDown += IconBarMouseDown;5
textArea.ToolTipRequest -= TextArea_ToolTipRequest;6
textArea.ToolTipRequest += TextArea_ToolTipRequest;7
}
此方法即用以绑定需要鼠标悬浮提示的TextEditor控件,在SharpPad项目的Open菜单类方法中调用此类绑定编辑控件。
注意上面的方法中可以看到ICSharpCode.TextEditor控件是通过其TextArea的ToolTipRequest事件公开给外部,用以分析并由外部提供ToolTip数据,而TextArea_ToolTipRequest(object sender, ToolTipRequestEventArgs e)方法中根据鼠标位置分析出要显示的数据后,最终调用e.ShowToolTip(toolTipText);用以设置提供数据。
1
static void TextArea_ToolTipRequest(object sender, ToolTipRequestEventArgs e)2


{
3
try4

{
5
TextArea textArea = (TextArea)sender;6
if (e.ToolTipShown) return;7
if (oldToolTipControl != null && !oldToolTipControl.AllowClose) return;8
if (!CodeCompletionOptions.TooltipsEnabled) return;9

10
if (CodeCompletionOptions.TooltipsOnlyWhenDebugging)11

{
12
if (currentDebugger == null) return;13
if (!currentDebugger.IsDebugging) return;14
}15

16
if (e.InDocument)17

{
18
Point logicPos = e.LogicalPosition;19
IDocument doc = textArea.Document;20
IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(textArea.MotherTextEditorControl.FileName);21
if (expressionFinder == null)22
return;23
LineSegment seg = doc.GetLineSegment(logicPos.Y);24
if (logicPos.X > seg.Length - 1)25
return;26
string textContent = doc.TextContent;27
ExpressionResult expressionResult

本文详细介绍了SharpDevelop的TextEditor组件,包括自动完成、代码折叠、鼠标悬停提示等功能的实现。通过ParserService和相关类库,解析代码并提供智能提示和文档描述。同时讨论了Parser的实现步骤,以及如何存储和加载分析数据,以提升效率。

5522

被折叠的 条评论
为什么被折叠?



