-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IJ插件开发 #2
Comments
第一个插件:
之后你会发现class与icon会变红(默认),如下图: 5.2 Plugin的代码如下
完成 |
VFS简介虚拟文件系统(VFS)是一个Intellij Platform组件,它封装了大部分对活动文件的处理操作,为了达成以下目的: 为了达到后两个目的,VFS为用户磁盘上的内容管理了一个持久化的快照,快照只存储那些通过VFS API访问过的和被异步更新后发生变化了的文件。快照是应用程序级别而不是工程级别的,也就是说,如果一个文件被多个项目引用,它的内容只会在快照中存在一个副本。所有的VFS访问操作都要经过快照。 如果通过VFS API访问文件时该文件不存在于快照中,VFS将从磁盘中加载该文件并存入快照,然后从快照返回数据。快照中只存储那些可被直接访问的信息,例如一个文本文件的内容会被全部存入快照,而另一些不可被直接访问的内容例如jar文件等,VFS只会存储它的元数据,例如文件名、文件尺寸和时间戳等。快照这一特性意味着IDE中显示的文件系统和文件内容可能并不总是能匹配磁盘上的实际内容。在IDE中,有一个观察者进程会从文件系统中接收到文件更改的通知并通知IDE进行刷新操作,刷新操作基于文件的时间戳,如果文件内容被更改而时间戳维持不变的话IDE将不会更新该文件的内容到快照。 获取VirtualFile从IOFile获取假设我们已经有一个位于磁盘上的io.java文件,要将其添加到VFS,可通过如下操作进行: 其中refresh方法的两个参数分别为是否进行异步刷新和是否进行递归刷新。通过以上代码逻辑即可获得IOFile在VFS中的实例。 使用FileChooser获取SDK中为我们提供了文件选择组件,通过简单的步骤可以直接获得一个VirtualFile实例: 从URL获取VirtualFileManager类提供了findFileByUrl()和refreshAndFindFileByUrl()方法让我们可以从URL获取VirtualFile实例 从VFS获取IDE所有的文件访问都要通过VFS,上述几种方式最终都是将文件添加到VFS的快照之后再提供访问。当文件已经被快照管理时,可以通过FilenameIndex.getFilesByName()获取到VirtualFile实例。 写入内容到VirtualFile正如Android不允许在UI线程中进行耗时操作一样,Intellij Platform也不允许在主线程中进行实时的文件写入,而需要通过一个异步任务来进行。 ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
new WriteCommandAction(project) {
@Override
protected void run(@NotNull Result result) throws Throwable {
//writing to file
}
}.execute();
}
}); 上面是一个写入文件的示例,需要说明的是,WriteCommandAction也并不是实时写入的,如果有多个WriteCommandAction操作,可能会被合并到某一时间同时执行写操作,所以如果在一组WriteCommandAction中有对不同文件的写操作,而该文件在这组操作中是动态获取的,那么最好在写操作执行前先将WriteCommandAction与文件建立一个映射关系。 |
PSI简介PSI(Program Structure Interface)是Intellij Platform中一个非常重要的概念,在IDE所管理的Project中,每个目录,Package,源代码和资源文件都会被抽象成相应的PSI对象。本文将以PsiDirectory、PsiJavaFile和XmlFile为例介绍插件对文件目录、Java类和DOM对象的操作。 一些有用的方法通用方法FilenameIndex.getFilesByName()通过给定名称(不包含具体路径)搜索对应文件 Java专用方法ClassInheritorsSearch.search()搜索一个类的所有子类 实例1下面通过一个实例,使用PSI对象创建一个目录,并在目录中创建一个Java类。 创建目录获取Project根目录 递归查找要创建的目录 判断要创建的目录是否已存在 如不存在,创建新目录
创建Java类创建PsiClass 添加package字段 实例2接下来的实例演示如何操作DOM对象 操作从外部读入的DOM获取XmlFile实例
遍历所有深度为1的Tag
生成XmlFile并写入文件创建XmlFile 向XmlFile写入属性
写入文件
|
支持未知类型的语言定义基础语言描述IDE之所以能仅通过扩展名就能识别出源文件所使用的语言,就是因为IDE内定义的Language和FileType为其提供了支持。 定义Language简单继承Language类,在构造函数中传入语言ID和其他参数即可。 定义文件类型继承LanguageFileType类,在实现的方法中分别返回源文件的名称、描述、默认扩展名和Icon即可。 定义FlieTypeFactory继承FileTypeFactory类,在createFileTypes方法中注册语言,并在plugin.xml的extensions节点中通过fileTypeFactory标签注册Factory。 完成以上几步后IDE便能通过文件扩展名识别出源文件并为其应用图标。 定于词法和语法规范定义Token和Element 定义语法IDEA支持通过BNF范式来定义语法,按照规则编写一个bnf文件,当语法被定义完成后,可以通过IDE生成PsiElement定义和PSI Parser。 定义Lexer词法分析器定义了一个文件的内容是如何被分解为Token的,创建Lexer的一个简单的方式是使用JFlex。定义一个lexer规则文件然后通过IDE即可生成Lexer。 以上便是为语言做最基础支持的步骤,完成文件类型和语法、词法分析器注册后,IDE便能为自定义语言提供文件识别、关键字检查和语法检查等支持。下面结合对weex-language-support插件的开发过程,介绍对扩展了html语法的weex脚本所做的语法高亮、自动提示、Lint等其它一系列的支持的实现。 weex语言支持识别weex脚本由于weex脚本文件的结构和html类似,均包括<script>、<style>标签和模板部分,所以我们的Language选择直接继承HTMLLanguage
定义完FileType之后,还需要实现一个对应的FileTypeFactory:
最后在plugin.xml内注册
完成这一步之后,IDE便能正确将以we作为扩展名的文件识别为weex文件,因为继承了HTMLLanguage,html语言原有的js和css的自动补全和lint规则也将被一并继承过来。 支持Weex DSL 自定义标签支持
如此在输入标签的时候IDE就能将weex标签加入自动补全列表中。
此处的关键是如何将XmlTag与它的声明文件即PsiFile关联起来,此处的桥梁就是XmlElementDescriptor。创建一个实现了XmlElementDescriptor的类,在getDeclaration()方法中返回PsiFile对象,如此便能在执行Open Declaeation的时候跳转到该tag的声明文件内。
最后,为了应用上述实现的功能,需要在plugin.xml中进行注册:
自定义标签属性支持按照上面的套路,大家肯定能想到标签属性也是有相应的Provider支持的,它就是XmlAttributeDescriptorsProvider,创建相应的实现类,实现以下方法: 同样地,最后需要在plugin.xml中进行注册:
自动补全支持
并不是所有IDE都包含JavaScript模块,本插件开发过程中选择IDEA 15作为SDK,并手动将/Applications/IntelliJ IDEA 15.app/Contents/plugins/JavaScriptLanguage目录下的jar文件添加到Project Structure的Classpath中。 CompleteType 创建我们自己的CompletionProvider,实现addCompletions方法:
如此就可以在输入标签属性值的时候触发补全逻辑,此处的难点在于如何从js中分析出函数和变量名,并分析出变量的类型和标签属性值的类型是否匹配,处于篇幅限制并未详细解释,如果想了解可以查看weex-language-support的源码或向我咨询。
CompletionContributor不能支持情况下的补全 在此处我们依旧获取了js中导出的所有变量,并创建了一个多级下拉框来供用户选择需要插入的变量值。顺带稍微介绍一下IDEA内置的一系列魔改Swing控件,这些控件大部分以JB开头,例如JBTable,JBColor等,编写插件时使用这些控件能保持与IDE一致的外观风格,让插件没有违和感。此处我们使用ListPopup控件来实现选择列表,通过JBPopupFactory.getInstance().createListPopup可以获得相应的ListPopup实例,并且可以调用ListPopop#showInBestPositionFor方法让ListPopup显示在屏幕上最恰当的位置(光标附近)。
Lint 创建Annotation 附加QuickFix Find Usages
最后在plugin.xml中注册:
|
If DataContext object is available final Editor editor = CommonDataKeys.EDITOR.getData(context); 通过CodeInsightTestFixtureImpl能够调用的方法
比如讲一个三元运算符转换为if语句:可以使用下面的测试用例
|
https://moxun.me/archives/28
The text was updated successfully, but these errors were encountered: