編寫一個不錯的開源項目至少有3個好處:html
(1)練技術,長經驗java
(2)面試時展示本身的Coding能力node
(3)獲取成就感git
練技術,長經驗是最實在的,不過若是本身有一個好的開源項目,還能夠在開源中國或github上開源,讓更多人受益,也許能得到許多的Star,讓自已得到知足,激勵本身完善項目功能。在面試時,也能夠在簡歷顯眼的位置給出開源項目名稱和Git地址。面試官通常都會去查看,這是程序員實力的最好見證,是本身Coding能力的最好見證。因此若是要編寫一個面試時拿的出手的項目,首先須要作到「規範」,下面談一下我眼中規範的開源項目。程序員
README.md文件是一個項目的入門手冊,裏面介紹了整個項目的使用、功能等等。因此README文件寫得好很差,關係到這個項目能不能更容易的被其餘人瞭解和使用。github
首先最起碼要作到的就是格式要清晰,讓人一眼能看出層次感,例如分幾個大標題對項目進行介紹,最簡單的就是分爲以下的4部分:面試
開發一個相似Eclipse AST View的插件,安裝的過程見以下博文: 框架
https://www.cnblogs.com/nettee/p/4463841.html
這個插件的詳細使用說明的連接以下:eclipse
https://www.eclipse.org/jdt/ui/astview/
安裝後就能夠直觀地查看抽象語法樹了,舉個例子,以下:jsp
package com.compiler;
import java.util.List;
public class C {
public void test(List<String> list){
list.add("a");
}
}
語法樹以下:
不過這個插件顯示的是基於Eclipse JDT中的增量式編譯器ECJ的抽象語法樹,而咱們常用的OpenJDK中的Javac編譯器的抽象語法樹與ECJ的抽象語法樹並不相同,不過絕大多數的語法樹節點劃分是同樣的,可是有少許的節點劃分不同,我打算開發一個相似Eclipse AST View的插件,用來顯示Javac編譯器的抽象語法樹。
開發這樣的插件須要瞭解JDT編譯器和Javac編譯器的抽象語法樹,同時還須要掌握Eclipse下的插件開發,參考的相關資源以下:
第一本就是《Eclipse插件開發學習筆記》,開發Eclipse插件必需要有插件開發相關基礎,這本書發版時間很早,可是插件開發的基本思想是不會變的。另外官方的Eclipse API也是開發中必不可少的資料。
Eclipse JDT中的增量式編譯器ECJ的抽象語法樹能夠經過博文Eclipse AST抽象語法樹API來了解,沒有相關的書籍。不過因爲是在Eclipse中開發插件,因此直接調用Eclipse相關API來獲取抽象語法樹就能夠了,不須要自已編寫Java源代碼轉換爲抽象語法樹的代碼實現。因此Eclipse AST View整個項目的實現也相對簡單。
不得不說,閱讀別人的代碼也是學習的最好方式之一。
編寫的插件中主要使用了樹插件,JFace爲樹控件提供了查看器Viewer。在查看器框架中,將模型稱爲輸入,查看器自己充當控制器的角色,而樹控件自己做爲視圖,當輸入改變時,查看器負責相應地改變控件的內容。
查看器框架主要由如下幾部分構成。
(1)模型和元素-存儲着要顯示在控件中的數據模型,咱們編寫的抽象語法樹節點模型以下:
package astview;
import java.util.ArrayList;
import java.util.List;
public class JavacASTNode {
private int id;
private String name;
private List<JavacASTNode> children;
private JavacASTNode parent = null;
public JavacASTNode() {
children = new ArrayList<JavacASTNode>();
}
public List<JavacASTNode> getChildren() {
return children;
}
public void setChildren(List<JavacASTNode> children) {
this.children = children;
}
public JavacASTNode getParent() {
return parent;
}
public void setParent(JavacASTNode parent) {
this.parent = parent;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
(2)內容提供者和標籤提供者-負責將數據模型轉化成能夠顯示的圖片和文字。我編寫的內容提供者以下:
class ViewContentProvider extends ArrayContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
JavacASTNode node = (JavacASTNode) parentElement;
return node.getChildren().toArray();
}
public Object getParent(Object element) {
JavacASTNode node = (JavacASTNode) element;
return node.getParent();
}
public boolean hasChildren(Object element) {
JavacASTNode node = (JavacASTNode) element;
return node.getChildren().size() > 0 ? true : false;
}
public Object[] getElements(Object inputElement) {
JavacASTNode compilatinUnitNode = new JavacASTNode();
compilatinUnitNode.setId(001);
compilatinUnitNode.setName("JCCompilationUnit");
JavacASTNode importNode = new JavacASTNode();
importNode.setId(002);
importNode.setName("JCImport");
JavacASTNode classNode = new JavacASTNode();
classNode.setId(003);
classNode.setName("JCClassDecl");
compilatinUnitNode.getChildren().add(importNode);
compilatinUnitNode.getChildren().add(classNode);
importNode.setParent(compilatinUnitNode);
classNode.setParent(compilatinUnitNode);
return new JavacASTNode[] {compilatinUnitNode};
}
}
這個類是JavacTreeViewer的內部類。咱們只簡單寫了一些測試用的數據,其實這些數據都是要從Javac編譯器中讀取的,而Javac編譯器分析的Java源代碼又須要從當前激活的編輯器中獲取,後面我會不斷完善更新這些功能。
編寫的標籤提供者以下:
class ViewLabelProvider extends LabelProvider {
public Image getColumnImage(Object element) {
return null;
}
public String getColumnText(Object element) {
return ((JavacASTNode) element).toString();
}
}
這個類也一樣是JavacTreeViewer的內部類。
(3)控件,用來顯示內容,這裏用到的爲樹控件TreeViewer
(4)查看器
模型和元素以及內容提供者和標籤提供者須要本身編寫,控件和查看器不須要開發者本身編寫。
編寫JavacTreeViewer類,以下:
package astview;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
public class JavacASTViewer extends ViewPart {
public static final String ID = "javacastviewer";
private TreeViewer viewer;
public void createPartControl(Composite parent) {
viewer = new TreeViewer(parent, SWT.SINGLE);
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setContentProvider(new ViewContentProvider());
viewer.setInput(getSite());
}
public void setFocus() {
// not supported
}
...
}
最後運行後,查看JavacTreeViewer視圖,顯示效果以下:
最後就是上傳到github了,個人github倉庫地址爲:
https://github.com/mazhimazh/JavacASTViewer
接下來我會不斷開發完善這個項目,若是各位能給個「Star」是最好了,你的支持是我繼續開發的最大動力。