Extending Eclipse Java Search - java

I'm developing an eclipse plugin where a user can search a java code given some text query, similar to the usual java search dialog in eclipse.
I'm using the following code to search for a text provided by user
SearchPattern pattern = SearchPattern.createPattern("<search_string>",
IJavaSearchConstants.TYPE, IJavaSearchConstants.PARAMETER_DECLARATION_TYPE_REFERENCE,
SearchPattern.R_EXACT_MATCH);
// step 2: Create search scope
// IJavaSearchScope scope = SearchEngine.createJavaSearchScope(packages);
IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
// step3: define a result collector
SearchRequestor requestor = new SearchRequestor()
{
public void acceptSearchMatch(SearchMatch match)
{
System.out.println(match.getElement());
}
};
// step4: start searching
SearchEngine searchEngine = new SearchEngine();
try {
searchEngine.search(pattern, new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, scope, requestor,
null);
} catch (CoreException e) {
e.printStackTrace();
}
Also I'm able to pass the query string from Search Dialogue to a class implementing ISearchPage.
public class QuerySearchPage extends DialogPage implements ISearchPage
{
...
public boolean performAction()
{
System.out.println(txtQuery.getText());
search();//search using the SearchEngine
SearchOperation so = new SearchOperation(iFileSet);
IRunnableWithProgress query = so;
try
{
container.getRunnableContext().run(true, true, query);
}
catch (InvocationTargetException | InterruptedException e)
{
e.printStackTrace();
}
return true;
}
}
Finally I got stuck at the point where I need to pass the search result to ISearchResultView. Basically, I have two questions:
Matched results are of type Object. How to pass these results to ISearchResultView which takes IFile as input?
How to get results in the below format?
I have already gone through the following links:
http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fsearch_page.htm
http://agile.csc.ncsu.edu/SEMaterials/tutorials/plugin_dev/
http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/3.5.2/org.eclipse/search/3.5.1/org/eclipse/search/ui/ISearchResult.java?av=f
http://codeandme.blogspot.de/2015/07/a-custom-search-provider.html
http://scg.unibe.ch/archive/projects/Bals10b-EclipsePlugins.pdf
How can I develop Eclipse search Plugin?
http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fsearch%2Fui%2FISearchResult.html
https://wiki.eclipse.org/FAQ_How_do_I_implement_a_search_operation%3F
Any help is highly welcomed.

Usually, you would implement a ISearchResultPage that is capable of displaying the search result. In its createControl() method you need to create a viewer that knows how to present the matches.
A commonly used abstract implementation of ISearchResultPage is AbstractTextSearchViewPage. This class uses a TableViewer or a TreeViewer to present the machtes, depending on whether they are hierarchical or not. In case you use the latter, implement its configureTreeViewer() and/or configureTableViewer() methods so that the viewers are equipped with label providers and content providers that know the specific type that represents a match, i.e. what you referred to as the 'Matched results of type Object'.
The AbstractTextSearchViewPage constructor must be told which kinds of layouts it supports: FLAG_LAYOUT_FLAT and/or FLAG_LAYOUT_TREE. The actual representation can be changed with setLayout().
To start with you could restrict the search view page to a flat layout and implement its configureTableViewer() like this:
viewer.setLabelProvider( new MyLabelProvider() );
viewer.setContentProvider( new MyContentProvider() );
The input for the content provider is your ISearchResult implementation. Hence the MyContentProvider could obtain the elements to be shown from the search result.
#Override
public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) {
searchResult = ( MySearchResult )newInput;
}
#Override
public Object[] getElements( Object inputElement ) {
return searchResult.getElements();
}

Related

SWT problems with saving data in the data base

I am trying to make an editable table by using swt, while I have trouble to save dates which are
modified in the database by using toplink:
if (referenceViewId.equalsIgnoreCase(TISTableViewPart.ID)) {
//TODO YUCHEN : Register and save objects in db
System.out.println("test");
final IViewPart viewPart = workbenchPage.findView(TISTableViewPart.ID);
final TISTableViewPart vdv = (TISTableViewPart) viewPart;
WorkingUnitMasterDataImpl sessionUow = new WorkingUnitMasterDataImpl();
Object test = vdv.getLocalComposite().getTableViewer().getElementAt(1);
sessionUow.registerObject(test);
try {
sessionUow.commitAndResume();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
By using
Object test = vdv.getLocalComposite().getTableViewer().getElementAt(1);
I can only get the object of the first colomne of the table, then I use
sessionUow.registerObject(test);
to save the change. Does someone have idea to get the whole table as an object in order to register and commitResume? Thanks in advance.
If you are using a TableViewer properly set up with a ContentProvider, it is assumed that the ContentProvider holds the all the elements the table contains.
Try to access these elements through the getElements() method in case you content provider implements IStructuredContentProvider.
Object[] elements = tableViever.getContentProvider().getElements();
In case you want to register to object changes, you can do that in the method setInput() ofthe ContentProvider. Indeed the javadoc for the IContentProvider interface suggests this method as the place for registering to changes.
If you need to access the input at a certain moment, the TableViewer object gives you access to your table input through the getInput() method:
Object tableInput = tableViewer.getInput();
Good luck!

How to parse a method or any other valid expression using JavaParser

JavaParser is a java source code parsing tool. I read the documents but found it only able to parse source of a full java class, like:
public class X {
public void show(String id) {
Question q = Quesiton.findById(id);
aaa.BBB.render(q);
}
}
But I want to parse only part of it, e.g. the method declaration:
public void show(String id) {
Question q = Quesiton.findById(id);
aaa.BBB.render(q);
}
How to do it or is it possible? If not, is there any other tool can do this?
Update
Actually I want to parse any valid expression in java, so I can do this easily with JavaParser:
CompilationUnit unit = JavaParser.parse(codeInputStream);
addField(unit, parseField("public String name")); // not possible now
I see you can include the method in a dummy class and parse it as usual. For the example you provided, enclose it inside:
public class DUMMY_CLASS_FOO {
// The string you're trying to parse (method or whatever)
}
Then you parse it as usual and neglect your dummy class while parsing.
UPDATE:
For the update you provided, you may try and catch
If the previous enclosure didn't do it, so enclose it into:
public class DUMMY_CLASS_FOO {
public void DUMMY_METHOD_FOO {
// Anything here
}
}
You might also search for Access Level Modifiers (public, private, ...etc), and if found, do the 1st solution. If not found, do the other one.

Refactor procedural method using OO principles

I have a method where I want to factor out some code into its own method
This is what I have:
public class TD0301AssignmentForm extends Form {
public TD0301AssignmentForm(TD0301AssignmentDAO dao, STKUser authenticatedUser) {
this.dao = dao;
this.authenticatedUser = authenticatedUser;
}
public Object insert(HttpServletRequest request) {
TD0301Assignment tdas = new TD0301Assignment();
TD0301Assignment tdas_orig = null;
Date dateNow = new Date();
try {
// Get the inuput from HTML form
tdas.setCalc_num(FormUtil.getFieldValue(request, FIELD_CALC_NUM));
processDate(request, tdas);
tdas.setCalc_dept(FormUtil.getFieldValue(request, FIELD_CALC_DEPT));
tdas.setYear_oi(Integer.toString(DateUtil.getIntYear(dateNow)));
processCalcSafetyRequirements(request, tdas);
...etc...
if (isSucces()) {
// Instantiate a base work flow instance!
WorkflowInstance wfi = new WorkflowInstance();
WorkflowInstanceDAO wfiDAO = new WorkflowInstanceDAO();
wfi.setWorkflow_class_id(tdas.getCalc_level());
wfi.setStarted_by(authenticatedUser.getBadge());
wfi.setStatus("0");
wfi.setLast_date(dateNow);
// Insert the WorkFlowInstance into the database, db sets returned sequence number into the wfi object.
wfiDAO.insert(wfi, authenticatedUser);
// Insert the TD0301Assignment into the db
tdas.setWorkflow_instance_id(wfi.getWorkflow_instance_id());
}
I'd like to remove the WorkflowInstance code out into its own method (still in this Class) like this:
if (isSucces()) {
insertWorkFlowInstance(request, tdas);
tdas.setWorkflow_instance_id(wfi.getWorkflow_instance_id());
but wfi is now marked by Eclipse as not available. Should I do something like this to fix the error so that I can still get the wfi.getWorkflow_instance_id() in the isSuccess block above? I know it removes the error, but I am trying to apply best practices.
public class TD0301AssignmentForm extends Form {
private WorkflowInstance wfi = new WorkflowInstance();
private WorkflowInstanceDAO wfiDAO = new WorkflowInstanceDAO();
Instance variables ("properties" or "fields") are not necessarily the way to go if they're not used throughout the entire class.
Variables should have the smallest scope possible--this makes code easier to reason about.
With some noise elided, and also guessing, it seems like the WorkflowInstance and WorkflowInstanceDao could be localized (names changed to match Java conventions):
public class TD0301AssignmentForm extends Form {
public Object insert(HttpServletRequest request) {
TD0301Assignment tdas = new TD0301Assignment();
try {
tdas.setCalcNum(FormUtil.getFieldValue(request, FIELD_CALC_NUM));
processDate(request, tdas);
tdas.setCalcDept(FormUtil.getFieldValue(request, FIELD_CALC_DEPT));
tdas.setYearOi(Integer.toString(DateUtil.getIntYear(dateNow)));
processCalcSafetyRequirements(request, tdas);
if (isSuccess()) {
WorkflowInstance wf = buildWorkflow(tdas);
tdas.setWorkflowInstanceId(wf.getId());
}
}
}
private buildWorkflow(TD0301Assignment tdas) {
WorkflowInstance wfi = new WorkflowInstance();
wfi.setWorkflowClassId(tdas.getCalcLevel());
wfi.setStartedBy(authenticatedUser.getBadge());
wfi.setStatus("0");
wfi.setLastDate(new Date());
WorkflowInstanceDao wfiDao = new WorkflowInstanceDao();
wfiDao.insert(wfi, authenticatedUser);
}
}
Whether or not this is appropriate depends on how/if the WorkflowInstance is used in the rest of the method snippet you show. The DAO is almost certainly able to be localized.
As methods become smaller and easier to think about, they become more testable.
For example, buildWorkflow is almost easy to test, except that the DAO is instantiated "manually". This means that testing the method will either (a) depend on having a working DAO layer, or (b) it must be mocked by a framework that can mock static utility methods (several can).
Without seeing all your code it's not easy to see exactlywhat you are trying to achieve. The reason eclipse is complaining is because it no longer has a wfi instance to play with because you've moved its local instance into your method, but creating another wfi instance is not likely to be your answer.
To get this working change the wfi to be class local and either use it's id directly or return wfi.getWorkflow_instance_id() from insertWorkFlowInstance() and then pass that value into tdas.setWorkflow_instance_id()

PropertyModel Expression's Exception : org.apache.wicket.WicketRuntimeException: No get method defined for class:

I used PropertyModel as the part of my DropDownChoice as following:
List<String> choices = Arrays.asList(new String[] { "Library", "School Office", "Science Dept" });
String selected = "Library";
DropDownChoice<String> serviceDDC =
new DropDownChoice<String>("service", new PropertyModel(this, "choices.0"), choices);
Somehow I've got this exception thown:
caused by: org.apache.wicket.WicketRuntimeException: No get method defined for class: class com.samoo.tool.pages.CreatePrintingJob expression: choices
at org.apache.wicket.util.lang.PropertyResolver.getGetAndSetter(PropertyResolver.java:481)
at org.apache.wicket.util.lang.PropertyResolver.getObjectAndGetSetter(PropertyResolver.java:332)
at org.apache.wicket.util.lang.PropertyResolver.getObjectAndGetSetter(PropertyResolver.java:242)
at org.apache.wicket.util.lang.PropertyResolver.getValue(PropertyResolver.java:95)
at org.apache.wicket.model.AbstractPropertyModel.getObject(AbstractPropertyModel.java:130)
at org.apache.wicket.Component.getDefaultModelObject(Component.java:1724)
....
I know that there's something wrong with the expression. I've been trying different parameter inputs but it still doesn't work. Could anyone help?
Since you're using PropertyModel(this, "choices.0"), Wicket is trying to find a property named choices via reflection through a method getChoices() of the class declaring the PropertyModel. This method doesn't seem to exist in com.samoo.tool.pages.CreatePrintingJob, as the exception is stating.
Also, if that 0 is an index, you should be accessing it with the [index] expression, as this JIRA issue suggests: PropertyModel does not support index only property ("[0]")
However, it seems you want to initialize the DropDownChoice to the first element of choices. But What Wicket will do if you set the DropDownChoice's Model to PropertyModel(this, "choices.[0"]) will be mapping the selection of this DropDownChoice in the following way:
At form rendering time to present the (pre)selected choice, it will use the first element in the choices list.
At form submission time to store the user selected value, it will store the selection in the first position of the choices list.
Summarising, the backing object representing the DropDownChoice's selection would be the first element in the choices list.
So, you'll probably want to use a whole different Model, independent from the choices list, for the backing object representing the DDC's selection.
List<String> choices = Arrays.asList(new String[] { "Library", "School Office",
"Science Dept" });
String selected = "Library";
IModel dropdownModel = new Model<String>(choices[0]);
DropDownChoice<String> serviceDDC =
new DropDownChoice<String>("service", dropdownModel, choices);
You might find the following links useful:
Using the DropDownChoice component
Working with Wicket Models
you are declaring choices inside the method, in order to get the PropertyModel to work you need to declare it on a class level not on a method level. As #Xavi López pointed out the espression is not corret you nedd to use choices.[0]
It is good idea to use IModel instead of PropertyMOdel.PropertyModel has big problems in refactoring. In my cases I did it and the problems solved properly.Also I have override the toString() of my Topic object.
topicDropDown = new DropDownChoice<Topic>("topicOptions", new IModel<Topic>() {
#Override
public Topic getObject() {
return top;
}
#Override
public void setObject(Topic t) {
top = t;
}
#Override
public void detach() {
}
}, new LoadableDetachableModel<List<Topic>>() {
#Override
protected List<Topic> load() {
List<Topic> topics = top.getAllTopics();
return topics;
}
});

How to find whether a member variable is used in a method using code in eclipse jdt?

I have to find all the methods in a class that use a particular member variable. (like "References" in eclipse but I want to implement using code...)I use AST visitor pattern that visits FieldDeclaration to get the name and type of all the member variables. I also use visitor pattern that visits MethodDeclaration nodes to get the content of each method using getBody(). Now I have the field variable name, type and member method details. I thought I can use a string search on the content of each member method but for a variable name "a", search may return true for keywords like "class" and others too!!! Is there a way to find the usage of a particular variable corresponding to a fieldDeclaration?? (like Binding or something??) If so, what is the AST Node or Class?
Here's the code I used...
SimpleNameVisitor simpleNameVisitor=new SimpleNameVisitor();
//SimpleNameVisitor is the visitor pattern for SimpleName
simpleNameVisitor.process(mthd.getMethodBlock());
//mthd is the object that stores method details
for(SimpleName simpName:simpleNameVisitor.getIdentifiers()){
if(varName.contentEquals(simpName.getFullyQualifiedName())){
//varName is the field variable name
System.out.println("MethodName: "+mthd.getName());
return;
}
}
Here's the code that solved the problem(suggested by wjans;changed equals to contentEquals)
VariableDeclarationFragment fragment = ... ;
IBinding binding = fragment.getName().resolveBinding();
public boolean visitNode(SimpleName simpleName) throws Exception {
if (binding.toString().contentEquals(simpleName.resolveBinding().toString()) {
....
}
}
You can do something like this:
Keep a reference to the binding of your FieldDeclaration,
VariableDeclarationFragment fragment = ... ;
IBinding binding = fragment.getName().resolveBinding();
and use this to compare it with the bindings when visiting SimpleName's inside your MethodDeclaration
public boolean visitNode(SimpleName simpleName) throws Exception {
if (binding.equals(simpleName.resolveBinding()) {
....
}
}
To implement something like Find References in code, use the JDT SearchEngine.
SearchRequestor findMethod = new SearchRequestor() {
#Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
// analyze search match.
}
};
SearchEngine engine = new SearchEngine();
IJavaSearchScope workspaceScope = SearchEngine
.createWorkspaceScope();
SearchPattern pattern = SearchPattern
.createPattern(
"org.eclipse.e4.core.internal.contexts.EclipseContext.strategy",
IJavaSearchConstants.FIELD,
IJavaSearchConstants.REFERENCES,
SearchPattern.R_EXACT_MATCH);
SearchParticipant[] participant = new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() };
engine.search(pattern, participant, workspaceScope, findMethod,
new NullProgressMonitor());
See http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_int_core.htm for more details on java search, the java model, and the AST.
See https://bugs.eclipse.org/bugs/attachment.cgi?id=192205 for an example that uses search and then looks at the results by generating an AST.
Visit all SimpleNames within the body of each method in your class:
public boolean visit(SimpleName node) {
IBinding binding = node.resolveBinding();
if (binding instanceof IVariableBinding) {
IVariableBinding variable = (IVariableBinding) binding;
if (variable.isField())
//do whatever you wanna do with the field
System.out.println("field: " + node.toString());
}
return super.visit(node);
}

Categories