As with most noob problems this proves fairly simple once done, but initially the Eclipse APIs provide a nice baffling wall. Our code is still running in a org.eclipse.core.resources.IncrementalProjectBuilder derived class and thus has a reference to the IResource for the file we are interested in (in my specific example, for a JSP file that in turn has a qualified class name in it). To implement the JSP check we'll need to then search for a user class by qualified type name, then check if the class has a specific method.
Our first step is to check if the type exists. Initially we only want to look in the current project, so we'll need a reference to the IJavaElement for the project. It turns out we can get a reference to this from JavaCore by passing in the IProject, which we can get from our IResource for the file. This means checking if a type exists can be done similar to the following (given that we have IResource resource as the resource our builder is working on and String qualifiedTypeName containing the type name of interest):
... IJavaProject javaProject = JavaCore.create(resource.getProject()); IType type; //normally findType returns null if there is no such type but theoretically it can throw JavaModelException also try { type = javaProject.findType(qualifiedTypeName); } catch (JavaModelException jme) { throw new RuntimeException("Error trying to find type \"" + typeName + "\""); } boolean typeExists = null != type;Wonderous! Now to see if we can look for a method. The docs seem to suggest we can use the SearchEngine to do look for stuff in Java code, passing a suitable SearchPattern in. We also have to provide a SearchRequestor implementation to trap our results, though in our case all we want to do is count them. For the time being we'll just look for 0 or >0 though eventually we'll have to determine whats going on if there are 2+ matches. We'll wrap all this into a couple of classes to help us simplify coding against the Java model as most of our code really only cares if something is a valid type and whether a JavaBeans-style property exists, not how we figure that out. Here is draft 1 of the Eclipse class to aid us in figuring out if typenames and properties are valid:
package com.example.validator; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.core.search.SearchParticipant; import org.eclipse.jdt.core.search.SearchPattern; import com.active.commons.StringUtils; public class JavaClassInfo { private IJavaProject javaProject; private IType type; public JavaClassInfo(IProject project, String typeName) { javaProject = JavaCore.create(project); try { type = javaProject.findType(typeName); } catch (JavaModelException jme) { throw new RuntimeException("Error trying to find type \"" + typeName + "\""); } } public boolean hasProperty(String propertyName) { return hasMethod("get" + StringUtils.capitalize(propertyName)) || hasMethod("is" + StringUtils.capitalize(propertyName)); } private boolean hasMethod(String methodName) { //Guard: must be a valid type to have methods if (!isValidTypename()) { return false; } SearchPattern pattern = SearchPattern.createPattern( methodName, IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH); IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { type }); CountingSearchRequestor matchCounter = new CountingSearchRequestor(); SearchEngine search = new SearchEngine(); try { search.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, matchCounter, null); } catch (CoreException ce) { System.out.println("Couldn't find type: " + ce.getMessage()); ce.printStackTrace(); } if (matchCounter.getNumMatch() > 1) { System.out.println("Bit weird; " + matchCounter.getNumMatch() + " matches for " + methodName); } return matchCounter.getNumMatch() > 0; } public boolean isValidTypename() { return type != null; } }Note that the following implementation of SearchRequestor is used to count results:
package com.example.validator; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.core.search.SearchRequestor; public class CountingSearchRequestor extends SearchRequestor { private int numMatch; @Override public void acceptSearchMatch(SearchMatch match) throws CoreException { numMatch++; } public int getNumMatch() { return numMatch; } }
This will allow us to write code similar to the following to check on type/method existance:
JavaClassInfo classInfo = new JavaClassInfo(resource.getProject(), qualifiedTypeName); ... if (!classInfo.hasProperty(propertyName)) { //add a Marker discussing how dumb you are to have used a property that doesn't exist! }One step closer to having our in-Eclipse JSP checker.
2 comments:
Status4Everyone
visit here
gaana
"Great post! I appreciate how you broke down the process of working with the Eclipse JDT Plugin to interrogate the Java model. The step-by-step explanation makes it easier to grasp the complex relationship between Scala and Java, especially when trying to locate methods within a Java class. This is a valuable guide for anyone developing cross-language plugins or exploring advanced plugin architecture. Thanks for sharing!"
Digital Marketing Course In Ameerpet
Post a Comment