IntelliJ插件开发 - 工具方法

查找类

获取当前项目
@Nullable
public static Project findCurrentProject() {
	IdeFrame frame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
	Project project = (frame != null) ? frame.getProject() : null;
	if (isValidProject(project))
	  return project; 
	for (Project p : ProjectManager.getInstance().getOpenProjects()) {
	  if (isValidProject(p))
		return p; 
	} 
	return null;
}

@Nonnull
public static Iterable<Project> findValidProjects() {
	return (Iterable<Project>)Arrays.<Project>stream(ProjectManager.getInstance().getOpenProjects())
	 .filter(ApplicationUtil::isValidProject)
	 .collect(Collectors.toList());
}

private static boolean isValidProject(@Nullable Project project) {
	return (project != null && !project.isDisposed() && !project.isDefault());
}
获取当前选中的Editor
public static Editor getSelectedEditor(Project project) {
	FileEditorManager editorManager = FileEditorManager.getInstance(project);
	if (editorManager == null) {
		return null;
	}
	if (editorManager instanceof FileEditorManagerImpl) {
		return ((FileEditorManagerImpl)editorManager).getSelectedTextEditor(true);
	}
	FileEditor current = editorManager.getSelectedEditor();
	if (current instanceof TextEditor) {
		return ((TextEditor)current).getEditor();
	}
	return null;
}
获取Editor对应的PsiFile
public static PsiFile getPsiFile(@NotNull Editor editor) {
    return PsiDocumentManager.getInstance(Objects.requireNonNull(editor.getProject()))
            .getPsiFile(editor.getDocument());
}
Module与源文件夹
// 获取所有Module
Module[] modules = ModuleManager.getInstance(project).getModules();
// 查找某个psiFile所属的Module
Module module = ModuleUtil.findModuleForFile(psiFile);
// 查找所有的源文件夹
VirtualFile[] virtualFiles = ProjectRootManager.getInstance(project).getContentSourceRoots();
// 查找某个文件所在的源文件夹
VirtualFile sourceDirectory =  ProjectRootManager.getInstance(project).getFileIndex().getSourceRootForFile(virtualFile);
PSI
PsiClass psiClass = PsiTreeUtil.getChildOfType(psiFile, PsiClass.class);
String packageName = ((PsiJavaFile) psiFile).getPackageName();
PsiMethod psiMethod = PsiTreeUtil.findElementOfClassAtOffset(psiFile, offset, PsiMethod.class, false);
格式化代码

文件类型,可以从editor获取:psiFile.getLanguage().getID()

public static String formatContent(Project project, FileType fileType, String content, int start, int end) {
	String fileName = "fakeFile." + fileType.getDefaultExtension();
	PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText(fileName, fileType, content);
	CodeStyleManager.getInstance(project).reformatText(psiFile, start, end);
	return psiFile.getText();
}
打开diff窗口
public static void showDiff(Editor editor, String content) {
	DiffManager diffManager = DiffManager.getInstance();
	// 创建左侧编辑器的DiffContent
	VirtualFile file = EditorUtil.getPsiFile(Objects.requireNonNull(editor)).getVirtualFile();
	DiffContent leftContent = DiffContentFactory.getInstance().create(editor.getProject(), file);

	// 创建右侧提供的文本的DiffContent (fileType可以根据editor中文件类型动态获取)
	FileType javaFileType = FileTypeManager.getInstance().getFileTypeByExtension("java");
	DiffContent rightContent = DiffContentFactory.getInstance().create(editor.getProject(), content, javaFileType);

	// 打开diff窗口
	SimpleDiffRequest diffRequest = new SimpleDiffRequest(file.getName(), leftContent, rightContent
			, "Your version", "Recommend version");
	diffManager.showDiff(editor.getProject(), diffRequest);
}
读写锁

与代码相关的数据结构(PSI, VFS, Project root model)打交道时,必须使用读写锁,如果在UI线程中进行读操作可以不用读锁,写操作必须在UI线程,且需要在write action(WA)中操作。

ApplicationManager.getApplication().runReadAction(() -> {
	// do read action
});

WriteCommandAction.runWriteCommandAction(project, () -> {
	// do write action
});
获取两个字符串的diff
String str1 = "log.info(\"\")";
String str2 = "log.info(\"hello: {}\", name);";
int[] str1Chars = str1.chars().toArray();
int[] str2Chars = str2.chars().toArray();
List<Pair<Integer, String>> diffResult = new ArrayList<>();
Diff.Change changes = Diff.buildChanges(str1Chars, str2Chars);
for (Diff.Change change : changes.toList()) {
	if (change.inserted > 0) {
		Pair<Integer, String> diffPair = Pair.create(change.line0
				, new String(str2Chars, change.line1, change.inserted));
		diffResult.add(diffPair);
	}
}
后台线程与UI线程切换
// 切UI线程
ApplicationManager.getApplication().invokeLater(() -> {});
ApplicationManager.getApplication().invokeAndWait(() -> {});

// 切后台线程
ApplicationManager.getApplication().executeOnPooledThread(() -> {});
获取插件版本

pluginId从plugin.xml中id属性获取

String pluginId = "从plugin.xml中id属性获取";
public static String getVersion() {
    IdeaPluginDescriptor pluginDescriptor = PluginManagerCore.getPlugin(pluginId);
    if (pluginDescriptor == null) {
        return null;
    }
    return pluginDescriptor.getVersion();
}

当光标在方法内时,查找离它最近的一个类

PsiMethod psiMethod = PsiTreeUtil.findElementOfClassAtOffset(psiFile, offset, PsiMethod.class, false);
if (psiMethod != null && psiMethod.getBody() != null && psiMethod.getBody().getTextOffset() < offset) {
	PsiElement psiElement = psiFile.findElementAt(offset);
	// 光标最近语句引用的类
	PsiElement relativeElement = PsiUtil.getPrevSiblingOfType(psiElement, PsiExpressionStatement.class
			, PsiDeclarationStatement.class, PsiReferenceExpression.class);
	PsiClass relativePsiClass = Optional.ofNullable(relativeElement)
			.map(e -> {
				if (e instanceof PsiReferenceExpression) {
					return (PsiReferenceExpression) e;
				}
				return PsiTreeUtil.findChildrenOfType(e, PsiReferenceExpression.class).stream()
                        .reduce((first, second) -> second).orElse(null);
			})
			.map(e ->{
				PsiType psiType = psiExpression.getType();
				if (psiType != null) {
					return PsiUtil.resolveClassInType(psiType);
				}
				// 为null时说明这个语句没写完,只写了一个类定义,这时候需要调用advancedResolve才能获取到其对应的类型
				return Optional.of(psiExpression).map(e -> e.advancedResolve(true))
						.filter(r -> r instanceof ClassCandidateInfo).map(r -> ((ClassCandidateInfo) r).getElement())
						.orElse(null);
			})
			.orElse(null);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值