在Eclipse中打造定制的Copy Qualified Name

指定完整类名在各类开发配置中经常用到,特别在基于框架的开发中非常频繁,一般在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,大功告成,顺便设置了快捷键。效果如下:

 


在Eclipse中打造定制的Copy Qualified Name

 


在Eclipse中打造定制的Copy Qualified Name
 
在Eclipse中打造定制的Copy Qualified Name
 
在Eclipse中打造定制的Copy Qualified Name

你可能感兴趣的:(eclipse,copy,Class,name,name,jdt,qualified,复制类名)