最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
资料预览
给大家整理的视频资料:
给大家整理的电子书资料:
如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
PSI
Program Structure Interface,是IntelliJ平台中负责解析文件并创建句法和语义代码模型的层,为平台的许多功能提供支持。
VFS (Virtual File System) 虚拟文件系统是IntelliJ平台的一个组件,它封装了与以虚拟文件表示的文件进行操作的大部分功能。它主要具有以下几个目的:
- 提供一个通用的API,无论文件实际位于何处(磁盘上、存档中、HTTP服务器上等),都可以对文件进行操作。
- 跟踪文件的修改,并在检测到更改时提供文件内容的旧版本和新版本。
- 提供将附加持久数据与VFS中的文件关联的可能性。
常用API:
- com.intellij.psi.PsiFileFactory:文件相关操作,e.g.创建文件等。
- com.intellij.psi.PsiElementFactory: 元素相关操作,e.g.创建java方法、注解、字段、构造方法等。
- com.intellij.psi.PsiManager: 项目访问PSI服务的主要入口点,e.g.查找文件、查找文件夹等。
- com.intellij.psi.PsiClass:在java类查找元素,e.g.查找方法、字段、注解。
- com.intellij.psi.JavaPsiFacade: java元素查找等操作,e.g.查找类等。
PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(project);
PsiElementFactory psiElementFactory = PsiElementFactory.getInstance(project);
PsiManager psiManager = PsiManager.getInstance(project);
ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project);
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
// 查找项目中的文件
ProjectFileIndex projectFileIndex = ProjectFileIndex.getInstance(project);
// 管理VirtualFile
VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
IntelliJ平台中与代码相关的数据结构都由一个读写锁(RW lock)进行管理,必须在一个读或者写的Action中才能访问这些模型:PSI、VFS、Project root model.
WriteCommandAction.runWriteCommandAction(project, () -> {
// 写操作
});
类型转换
- 转VirtualFile
// 文件路径(String)转VirtualFile
VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
VirtualFile virtualFile = virtualFileManager.findFileByNioPath(Path.of(path));
// File转VirtualFile
File file= new File("./demo.java");
VritualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
virtualFile.refresh(false, true);
// PsiFile转VirtualFile
VirtualFile virtualFile = psiFile.getVirtualFile();
// URL转VirtualFile
VirtualFileManager.getInstance().findFileByUrl("url");
VirtualFileManager.getInstance().refreshAndFindFileByUrl("url");
- 转PsiDirectory / PsiFile / PsiClass
// VirtualFile转PsiDirector
PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(virtualFile);
// VirtualFile转PsiFile
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
// PsiClass转PsiFile
PsiJavaFile psiJavaFile = (PsiJavaFile) psiClass.getContainingFile();
// PsiType转PsiClass
PsiClass psiClass = ((PsiClassType)psiType).resolve()
查找类操作
- 查找Module / SourceRoot
// 获取所有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);
- 查找PsiFile / PsiClass / VirtualFile
// 根据类的QualifiedName查找PsiClass
PsiClass = JavaPsiFacade.getInstance(project).findClass(sourceClassStr, GlobalSearchScope.allScope(project))
// 根据类的SimpleName查找PsiClass
PsiClass[] classes = PsiShortNamesCache.getInstance(project).getClassesByName(StringUtils.capitalize(selectedText), GlobalSearchScope.allScope(project));
// 根据fileName查找VirtualFile
Collection<VirtualFile> vFiles = FilenameIndex.getVirtualFilesByName(fileName, GlobalSearchScope.projectScope(project));
PsiJavaFile / PsiClass 操作
- 从PsiJavaFile中获取PsiClass
// 从PsiJavaFile中获取Public属性的Class
PsiClass psiClass = Arrays.stream(psiJavaFile.getClasses())
.filter(x -> x.getModifierList() != null && x.getModifierList().hasModifierProperty(PsiModifier.PUBLIC))
.findFirst().orElse(null);
- 获取方法签名
// 获取所有的Method
PsiMethod[] methods = psiClass.getMethods()
// 获取方法签名
String methodSignature = Optional.ofNullable(psiMethod.getReturnType()).map(x -> x.getPresentableText() + " ").orElse("")
+ psiMethod.getName() + "(" +
Arrays.stream(psiMethod.getParameterList().getParameters())
.map(x -> x.getType().getPresentableText())
.collect(Collectors.joining(",")) + ")";
- 新建JavaFile (需要在WriteAction中进行写操作)
// 在指定PsiDirectory目录下,新建一个java类。content换行符如果是\r\n需要转换成\n
PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(psiDirectory.getProject());
PsiJavaFile psiJavaFile = (PsiJavaFile) psiFileFactory.createFileFromText(fileName, JavaFileType.INSTANCE, content);
psiDirectory.add(psiJavaFile);
PsiType操作
- 获取类名
// 获取PsiType的全类名,包含泛型,如: Result<List<TestDTO>>
String qualifiedName = psiType.getCanonicalText();
// 获取类名简称,可能返回void
String simpleName = psiType.getPresentableText();
// 获取PsiType对应的PsiClass
PsiClass psiClass = ((PsiClassType)psiType).resolve();
- 获取泛型
// 获取PsiType的泛型集合
List<PsiType> getGenericType(PsiType psiType) {
if (psiType instanceof PsiClassReferenceType) {
PsiClassReferenceType psiClassReferenceType = (PsiClassReferenceType)psiType;
return Arrays.stream(psiClassReferenceType.getParameters())
.filter(Objects::nonNull).collect(Collectors.toList());
}
return Collections.emptyList();
}
// 递归获取PsiType的所有PsiClass
List<PsiClass> getPsiClassWithGenericType(PsiType psiType) {
if (psiType instanceof PsiClassType) {
List<PsiClass> psiClasses = new ArrayList<>();
psiClasses.add(((PsiClassType)psiType).resolve());
List<PsiType> genericTypes = getGenericType(psiType);
if (!genericTypes.isEmpty()) {
for (PsiType genericType : genericTypes) {
psiClasses.addAll(getPsiClassWithGenericType(genericType));
}
}
return psiClasses;
}
return Collections.emptyList();
}
PsiElement操作(导包、加方法等)
- 创建PsiElement
PsiElementFactory psiElementFactory = PsiElementFactory.getInstance(project);
// 创建PsiStatement
psiElementFactory.createStatementFromText(statementStr, psiMethod)
// 创建PsiImportStatement
psiElementFactory.createImportStatement(psiClass)
// 创建PsiMethod, context传PsiElement类型,可以是PsiMehtod, PsiJavaFile, PsiStatement...
psiElementFactory.createMethodFromText(methodStr, context)
// 创建PsiType并获取PsiClass
PsiType psiType = psiElementFactory.createTypeFromText(qualifiedName, null);
PsiClass psiClass = ((PsiClassType)psiType)psiType.resolve();
// 创建PsiField
PsiField psiField = psiElementFactory.createFieldFromText("@Resource private Test test;", psiClass);
- 导入包
// 获取PsiElementFactory
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
PsiElementFactory psiElementFactory = javaPsiFacade.getElementFactory();
// 导入指定PsiClass (import xxx;)
Set<String> importSet = Optional.ofNullable(psiImportList).map(PsiImportList::getImportStatements)
.stream().flatMap(Arrays::stream)
.map(PsiImportStatement::getQualifiedName).collect(Collectors.toSet());
if (!importSet.contains(sourceClass.getQualifiedName())) {
WriteCommandAction.runWriteCommandAction(project, () -> {
psiImportList.add(psiElementFactory.createImportStatement(psiClass));
});
}
- 添加方法
PsiMethod psiMethod = psiElementFactory.createMethodFromText(methodText, psiJavaFile);
WriteCommandAction.runWriteCommandAction(project, () -> {
### 最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
### 资料预览
给大家整理的视频资料:
![](https://img-blog.csdnimg.cn/img_convert/c4b297c6f4184af85cb748236df7be4b.png)
给大家整理的电子书资料:
![](https://img-blog.csdnimg.cn/img_convert/c83f61e6b1bb2c68b729a561b3230448.png)
**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618635766)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
img-Q0hVcCDw-1715731313447)]
**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618635766)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**