指定完整类名在各类开发配置中经常用到,特别在基于框架的开发中非常频繁,一般在Eclipse IDE中的操作就是:在PackageExplorer或者Project Explorer中展开类结构树->Right Click->Context Menu->Copy Qualified Name。我在想能不能偷懒一步呢?如果不展开类结构树,默认的Copy Qualified Name命令复制得到的是相对于workspace的absolute path (以/作为起始)。并且,对于classpath下的资源执行Copy Qualified Name命令得到的也是相对于workspace的absolute path。实际开发中,很少需要这样的absolute path,需要的更多是相对于classpath下relative path。需求又来了,考虑添加一个自定义的命令到Eclipse中去。
很遗憾的是,尝试写一个自定义的Eclipse Plugin时,得到如下错误。MS无法获取无法加载到JDT的类。对Eclipse的class loader机制不太熟悉,也不去过多深究。只想尽快达到最初目的,于是,直接对Eclipse的JDT直接进行修改。还好,Eclipse目录下自带JDT的source,仔细查看源码改起来也不麻烦,虽知道这不是正道。
Caused by: java.lang.ClassNotFoundException: org.eclipse.jdt.core.ICompilationUnit
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
... 35 more
对JDT的Jar搜索一下"Copy Qualified Name"就能很快定位到位于org.eclipse.jdt.internal.ui.actions.CopyQualifiedNameAction中的关键代码。可以见到代码采用了getFullPath()。
private String getQualifiedName(Object element) throws JavaModelException {
if (element instanceof IResource)
return ((IResource)element).getFullPath().toString();
if (element instanceof IJarEntryResource)
return ((IJarEntryResource)element).getFullPath().toString();
if (element instanceof IJavaProject || element instanceof IPackageFragmentRoot || element instanceof ITypeRoot) {
IResource resource= ((IJavaElement)element).getCorrespondingResource();
if (resource != null)
return getQualifiedName(resource);
}
return TextProcessor.deprocess(JavaElementLabels.getTextLabel(element, LABEL_FLAGS));
}
对JDT代码进行了一番研究后,修改成如下:
private String getClassNameFromJavaFile(String javaElementName) {
if(javaElementName.endsWith(".java")) {
return javaElementName.substring(0, javaElementName.length() - 5);
} else if (javaElementName.endsWith(".class")) {
return javaElementName.substring(0, javaElementName.length() - 6);
} else {
return javaElementName;
}
}
private String getQualifiedName(Object element) throws JavaModelException {
// 1 java file
if (element instanceof ICompilationUnit) {
ICompilationUnit compilationUnit = (ICompilationUnit)element;
IPackageDeclaration[] packages = compilationUnit.getPackageDeclarations();
if(packages != null && packages.length > 0) {
return packages[0].getElementName() + "." + getClassNameFromJavaFile(compilationUnit.getElementName());
} else {
return getClassNameFromJavaFile(compilationUnit.getElementName());
}
}
// 2. Package下的resource file
if (element instanceof IResource) {
IResource resource = (IResource)element;
IContainer container = resource.getParent();
IJavaElement javaElement = null;
if (container.getAdapter(IJavaElement.class) != null) {
javaElement = (IJavaElement)container.getAdapter(IJavaElement.class);
}
if( javaElement != null ) {
IPackageFragmentRoot packageRoot = (IPackageFragmentRoot)javaElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
return resource.getProjectRelativePath().makeRelativeTo(
packageRoot.getResource().getProjectRelativePath()).toString();
}
return resource.getFullPath().toString();
}
// 3. Jar包中的class file
if(element instanceof IClassFile) {
IClassFile classFile = (IClassFile)element;
IPackageFragment packageFragment = (IPackageFragment)classFile.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
if(packageFragment != null) {
return packageFragment.getElementName() + "." + getClassNameFromJavaFile(classFile.getElementName());
}
}
// Jar包中的resouce file
if (element instanceof IJarEntryResource) {
return ((IJarEntryResource)element).getFullPath().toString().substring(1);
}
if (element instanceof IJavaProject || element instanceof IPackageFragmentRoot) { // || element instanceof ITypeRoot
IResource resource= ((IJavaElement)element).getCorrespondingResource();
if (resource != null)
return getQualifiedName(resource);
}
return TextProcessor.deprocess(JavaElementLabels.getTextLabel(element, LABEL_FLAGS));
}
本人加入若干判断分支并对原有代码做了修改,分别对应于不同元素类型的Copy Qualified Name
1)Package下的java file
2)Package下的resource file
3)Jar包中的class file
4)Jar包中的resouce file
代码看起来有点恶心,类型转换绕来绕去。不知有没有更简洁的~~~姑且这样,经我本地Eclipse测试反正是可以的。打包也是恶心,把改完编译好的class file重新塞进本地Eclipse的Plugin目录下的org.eclipse.jdt.ui_3.6.1.r361_v20100825-0800.jar中去。重新打开Eclipse,大功告成,顺便设置了快捷键。效果如下:





- 大小: 35.5 KB

- 大小: 30.4 KB

- 大小: 42.2 KB

- 大小: 30.1 KB
分享到:
相关推荐
用Copy Qualified Name复制类全名时 总是这样的/hb03/src/org/self/hb/entity/Account.java很不方便 可以这样解决 : 下载插件解压到Eclipse安装目录下 将那一个解压后的文件夹直接丢进安装目录下面的Myeclipse\...
java源码补丁生成器 使用说明: 01、设置文件路径resource/filePath.properties ... 0202、升级文件列表也可在eclipse中右键文件选择 Copy Qualified Name 复制文件全路径 03、执行start.bat文件生成补丁
为了实现"Copy Fully Qualified Class Name"这样的功能,我们需要将特定的插件添加到Eclipse中。在这个案例中,提供的压缩包`de.jave.eclipse.copyfully_1.1.0`很可能就是这样一个插件,它扩展了Eclipse的功能,允许...
- **Eclipse**: 右击--> `CopyQualifiedName` (右击--> `Copy Reference`) - **Android Studio**: `Ctrl+Shift+Alt+C` - **功能说明**: 复制类的完整路径,包括包名和类名。 **38. 大写/小写** - **Eclipse**: `...
嵌入式系统开发_STM32微控制器_ESP8266WiFi模块_心率传感器_加速度计_OLED显示屏_蓝牙40_低功耗设计_实时操作系统_智能手表_多功能健康监测_运动数据记录_
驾校自动化_网页自动化爬虫技术_Python27多线程HTTP请求模拟_龙泉驾校2014版约车系统自动预约助手_通过模拟登录和循环请求实现自动约车功能_支持失败自动递增车号重试_
Linux系统编程_操作系统内核_系统调用_进程线程_信号处理_文件IO_进程间通信_多线程同步_网络编程_UNIX环境编程_中文翻译勘误_错误修正_代码示例优化_技术文档校对_开
wanjunshe_Python-Tensorflow_12888_1745868924470
scratch少儿编程逻辑思维游戏源码-铅笔画.zip
即时通讯应用开发_基于LeanCloud云服务与Android原生开发_集成QQ第三方登录与即时聊天功能的社交应用_实现用户注册登录创建聊天室发送文字消息展示用户信息头像昵称并提供
scratch少儿编程逻辑思维游戏源码-伞兵大乱斗(云变量).zip
scratch少儿编程逻辑思维游戏源码-楼层酷跑.zip
scratch少儿编程逻辑思维游戏源码-零下之寒颤.zip
scratch少儿编程逻辑思维游戏源码-密室逃生.zip
少儿编程scratch项目源代码文件案例素材-爪猫足球.zip
命令行完成git本地仓库创建、将代码提交到暂存区、查看暂存区信息、将代码提交到本地仓库、将本地仓库关联到远程仓库、推送到远程仓库全过程的截图
少儿编程scratch项目源代码文件案例素材-纸.zip
scratch少儿编程逻辑思维游戏源码-日本冒险.zip
scratch少儿编程逻辑思维游戏源码-狼人杀跑酷.zip
scratch少儿编程逻辑思维游戏源码-史莱姆杀手.zip