IT教程 ·

第3篇-怎样编写一个面试时能拿的出手的开源项目?

《HelloGitHub》第 47 期

前2篇的链接以下:

 

 

第1篇介博文中细致引见过编写一个范例开源项目所要遵照的范例,而且开端完成了博主本身的开源项目,不过只搭建了项目开发的基础框架,树状组织的数据模型也是硬编码的;第2篇从Eclipse编辑器中读取Java源代码并转换为Javac的笼统语法树,然后又将Javac的笼统语法树转换为了Eclipse树形插件所辨认的数据模型,在视图中动态展示出来。本篇将为这个树形插件视图完美功用。主要就是增添读入、革新、睁开与折叠的功用按钮,同时双击树中的某个结点,选中Eclipse中对应的源代码信息。

1、增添读入、革新、睁开与折叠功用按钮

代码比较简朴,只须要定义响应的Action,然后增添到东西栏管理器IToolBarManager中即可。

定义的响应Action以下: 

private void makeActions() {
	
	
	fFocusAction = new Action() {
		@Override
		public void run() {
			performSetFocus();
		}
	};
	fFocusAction.setText("&Show AST of active editor");
	fFocusAction.setToolTipText("Show AST of active editor"); 
	fFocusAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_REFRESH);
	ASTViewImages.setImageDescriptors(fFocusAction, ASTViewImages.SETFOCUS);
	
	fRefreshAction = new Action() {
		@Override
		public void run() {
			try {
				refreshAST();
			} catch (CoreException e) {
				e.printStackTrace();
			}
		}
	};
	fRefreshAction.setText("&Refresh AST"); 
	fRefreshAction.setToolTipText("Refresh AST"); 
	fRefreshAction.setEnabled(false);
	ASTViewImages.setImageDescriptors(fRefreshAction, ASTViewImages.REFRESH);
	
	fCollapseAction = new Action() {
		@Override
		public void run() {
			performCollapse();
		}
	};
	fCollapseAction.setText("C&ollapse"); 
	fCollapseAction.setToolTipText("Collapse Selected Node"); 
	fCollapseAction.setEnabled(true);
	ASTViewImages.setImageDescriptors(fCollapseAction, ASTViewImages.COLLAPSE);

	fExpandAction = new Action() {
		@Override
		public void run() {
			performExpand();
		}
	};
	fExpandAction.setText("E&xpand"); 
	fExpandAction.setToolTipText("Expand Selected Node"); 
	fExpandAction.setEnabled(true);
	ASTViewImages.setImageDescriptors(fExpandAction, ASTViewImages.EXPAND);
	
	fDoubleClickAction = new Action() {
		@Override
		public void run() {
			performDoubleClick();
		}
	};

}

单击4个按钮后实行的对应行动由3个函数定义,以下: 

private void refreshAST() throws CoreException {
	internalSetInput(uri);
}

protected void performCollapse() {
	IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection();
	if (selection.isEmpty()) {
		fViewer.collapseAll();
	} else {
		fViewer.getTree().setRedraw(false);
		for (Object s : selection.toArray()) {
			fViewer.collapseToLevel(s, AbstractTreeViewer.ALL_LEVELS);
		}
		fViewer.getTree().setRedraw(true);
	}
}

protected void performExpand() {
	IStructuredSelection selection= (IStructuredSelection) fViewer.getSelection();
	if (selection.isEmpty()) {
		fViewer.expandToLevel(3);
	} else {
		fViewer.getTree().setRedraw(false);
		for (Object s : selection.toArray()) {
			fViewer.expandToLevel(s, AbstractTreeViewer.ALL_LEVELS);
		}
		fViewer.getTree().setRedraw(true);
	}
}

protected void performSetFocus() {
	IEditorPart part= EditorUtility.getActiveEditor();
	if (part instanceof ITextEditor) {
		try {
			setInput((ITextEditor) part);
		} catch (CoreException e) {
			showAndLogError("Could not set Javac AST view input ", e); //$NON-NLS-1$
		}
	}
}

performSetFocus()函数实行读入行动、refreshAST()函数实行革新行动、performCollapse()函数实行语法树合上行动,而performExpand()函数实行语法树睁开行动。能够睁开特定语法树节点,只需选中这个语法树节点,然后点击睁开按钮即可。  

向东西栏管理器中增添定义好的Action,以下: 

private void contributeToActionBars() {
	IActionBars bars = getViewSite().getActionBars();
	bars.getToolBarManager().add(fFocusAction);
	bars.getToolBarManager().add(fRefreshAction);
	bars.getToolBarManager().add(fCollapseAction);
	bars.getToolBarManager().add(fExpandAction);
	bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fFocusAction);
}

在createPartControl()函数中挪用相干要领,以下:

makeActions();
contributeToActionBars();

结果以下:

 

  

2、选中源代码功用

要选中Eclipse插件中某个局限的源代码,须要挪用相干函数,同时通报2个主要的参数,一个就是字符的入手下手位置pos,别的就是长度length。这两个参数我们能够直接从Javac的相干API中猎取,修正createAST()函数,以下:

public static EndPosTable ept = null;

private JCCompilationUnit createAST(URI is) {
	Context context = new Context();
	JavacFileManager.preRegister(context);
	JavaFileManager fileManager = context.get(JavaFileManager.class);
	JavaCompiler comp = JavaCompiler.instance(context);
	JavacFileManager dfm = (JavacFileManager) fileManager;

	JavaFileObject jfo = dfm.getFileForInput(is.getPath());
	comp.genEndPos = true;
	JCCompilationUnit tree = comp.parse(jfo);
	ept = tree.endPositions;	
     comp.parseFiles(otherFiles);

	return tree;
}

须要翻开JavaCompiler的genEndPos开关,如许Javac在剖析Java源代码字符流的过程当中,就会保留对应的语法树节点到字符完毕位置的对应关联,这个关联就保留在EndPostTable中,所以我们用全局变量ept保留即可。

在JavacASTNode中新定义2个属性,用来保留对应语法树节点在字符流中的入手下手与完毕位置,以下:

private int startpos,endpos;

然后修正JavacASTNode的组织函数,以下:

public JavacASTNode(int startpos,int endpos) {
	children = new ArrayList<JavacASTNode>();
	this.startpos = startpos;
	this.endpos = endpos;
}

在访问者要领中为这2个属性赋值,例如在visitCompilationUnit()和visitClass()要领中赋值,完成以下:

@Override
public JavacASTNode visitCompilationUnit(CompilationUnitTree node, Void p) {
	JCCompilationUnit t = (JCCompilationUnit) node;
	JavacASTNode currnode = new JavacASTNode(t.getStartPosition(),t.getEndPosition(JavacASTViewer.ept));
	currnode.setProperty("root");
	currnode.setType(t.getClass().getSimpleName());
	
	traverse(currnode,"packageAnnotations",t.packageAnnotations);
	traverse(currnode,"pid",t.pid);
	traverse(currnode,"defs",t.defs);

	return currnode;
}

@Override
public JavacASTNode visitClass(ClassTree node, Void p) {
	JCClassDecl t = (JCClassDecl) node;
	JavacASTNode currnode = new JavacASTNode(t.getStartPosition(),t.getEndPosition(JavacASTViewer.ept));

	traverse(currnode,"extending",t.extending);
	traverse(currnode,"implementing",t.implementing);
	traverse(currnode,"defs",t.defs);
	
	return currnode;
}

经由过程挪用节点类的getStartPosition()猎取入手下手位置,挪用getEndPosition()猎取完毕位置,不过挪用这个要领须要通报之前保留的EndPosTable信息。

定义监听器监听双击事宜,以下:

package astview.listener;

import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;

import astview.JavacASTViewer;

public class ListenerMix implements IDocumentListener,IDoubleClickListener {

	private JavacASTViewer fView;

	public ListenerMix(JavacASTViewer view) {
		fView= view;
	}

	public void dispose() {
		fView= null;
	}

	// ...

	@Override
	public void doubleClick(DoubleClickEvent event) {
		fView.handleDoubleClick();
	}
}

运用这个监听器,在createPartControl()中为fViewer增添监听器,以下:

fViewer.addDoubleClickListener(fSuperListener);

如许在双击语法树某个节点时,监听器会挪用fView.hanbndleDoubleClick()要领对行动做响应的处置惩罚,函数的完成以下:

protected void performDoubleClick() {
	if (fEditor == null) {
		return;
	}

	ISelection selection = fViewer.getSelection();
	Object obj = ((IStructuredSelection) selection).getFirstElement();
	if(obj!=null && obj instanceof JavacASTNode) {
		JavacASTNode node = (JavacASTNode)obj;
		EditorUtility.selectInEditor(fEditor, node.getStartpos(),node.getEndpos()-node.getStartpos());
	}
}

挪用EditorUtility东西类中的selectInEditor()要领,这个要领的定义以下:

public static void selectInEditor(ITextEditor editor, int offset, int length) {
	IEditorPart active = getActiveEditor();
	if (active != editor) {
		editor.getSite().getPage().activate(editor);
	}
	editor.selectAndReveal(offset, length);
}

挪用IEditorPart的selectAndReveal()要领,同时通报入手下手位置和选中的长度就完成了这个功用。  

3、宣布插件

宣布Eclipse插件异常简朴,网上相干的材料也异常多,这里就不做过量引见。作者将打包好的插件放到了项目的zip目次下,人人能够下载下来以Install的体式格局装置。

4、编写README.md

编写文档引见项目以及运用要领,具体内容以下:

# JavacTreeViewer
## 1、项目简介
以插件的情势直观的检察基于OpenJDK的编译器Javac的笼统语法树。
## 2、项目形貌
能够在Eclipse中以插件的体式格局装置、检察Javac的笼统语法树组织。类似于Eclipse AST View插件。Eclipse AST View插件显现的是ECJ编译器的笼统语法树,而JavacASTViewer显现的是基于OpenJDK的编译器Javac的笼统语法树组织。
## 3、用法
可直接下载项目源代码,本身导出Eclipse插件包,或许下载本项目中zip目次下作者打包好的插件包,以Install的体式格局装置。
现在只测试了Eclipse IDE for RCP and RAP Developers 4.14.0版本。

 

如许一个插件就开发完了,不过后续还须要增添更多的测试用例,以及完美更多的功用。

 

 

区块链技术基础原理与算法(比特币为例,主要是比特币的原理),密码学原理

参与评论