In one of my Android projects (but not necessarily tied to Android) I have quite a few method calls that really do nothing but blow up the code and could be automatically removed. Examples:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
#Override
public void onDestroy() {
super.onDestroy();
}
I couldn't find any inspections that help me in automatically removing these expressions, so I tried structural search. My attempt so far: I copied the template of 'annotated methods' and made 2 small changes.
$Annotation$ changed to occurs=1, text=Override
Added a $Statement$ variable with occurs=1
The template code:
class $Class$ {
#$Annotation$( )
$MethodType$ $MethodName$($ParameterType$ $ParameterName$) {
$Statement$;
}
}
So far, so good - it's only finding methods with a single line in the body. But now I want to explicitely search for exact statements calling the super method (kind of like a back reference to $MethodName$), but which also return the super value (when not void). Any ideas?
I believe this would be a really useful inspection that could be integrated into the main IntelliJ codebase as well. :-)
So I recently found out that IntelliJ's 'Empty method' inspection actually looks for this. Simply:
Double Shift -> Run Inspection By Name -> Empty method
The synopsis is 'Method only calls its super', but the inspection actually looks for more than just this, for example:
The method and all its derivables are empty
All implementations of this method are empty
The method is empty
Empty method overrides empty method
Depending on your situation it might find more than you want - and the refactoring tried to remove more than I actually wanted. But with a quick manual review you should be good to go. :-)
Using Structural Search you will have to use two separate searches. One for finding methods with void return type:
class $Class$ {
$MethodType$ $MethodName$($ParameterType$ $ParameterName$) {
super.$MethodName$($ParameterName$);
}
}
and a second for methods which return a value:
class $Class$ {
$MethodType$ $MethodName$($ParameterType$ $ParameterName$) {
return super.$MethodName$($ParameterName$);
}
}
Specifying the #Override annotation is unnecessary in this case.
Related
I use struts2 to build a login platform. I use an Interceptor extends MethodFilterInterceptor. In the method doIntercept, I use "actionInvocation.invoke()" instead of "return actionInvocation.invoke()". But it also run.
struts-2.5.18
public class loginInterceptor extends MethodFilterInterceptor {
#Override
protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
if (ServletActionContext.getRequest().getSession().getAttribute("user") != null){
actionInvocation.invoke();
}
return null;
}
}
I think because the method return null, it should not jump to the view. However, it does.
Please see the "Writing Interceptors" docs.
The important part:
[...] invoke will return after the result has been called (eg. after your JSP has been rendered), making it perfect for things like open-session-in-view patterns. If you want to do something before the result gets called, you should implement a PreResultListener.
I.e., if you call invoke, the interceptors and action will be executed as normal.
To short-circuit normal processing do not call invoke, instead return a result suitable to your purposes, e.g., a login page's global result.
I'm new to AOP and I need to use AspectJ on my project.
I need to use around advice but I have a problem using it, I've the following code in my .aj class,
pointcut checkUser(ProceedingJoinPoint jp,User user): call(* com.example.UserAccount.MyUI.checkUser(..))&& args(jp,user);
void around(ProceedingJoinPoint jp,User user) throws Throwable : checkUser(jp,user){
// Condition checks one of the user boolean property
if(condition){
jp.proceed();
}else{
// Do nothing
}
}
but I get this warning all the time,
advice defined in Aspects.UserAccount has not been applied [Xlint:adviceDidNotMatch]
By the way, I tried it without ProceedingJoinPoint and tried just proceed(); but then got this warning, too few arguments to proceed, expected 1
I'm thankful for any single help or hint!
Reza
First I recommend to read the AspectJ documentation in order to learn the syntax. As you are using native AspectJ syntax, this is like learning a new programming language or at least a Java extension. What you are doing is mix native syntax with annotation-based syntax. Try to stick with one. I am sure that you did not find this in any tutorial but ended up with that syntax via trial and error.
You do not need to bind a joinpoint parameter in native syntax because it is there implicitly and automatically. The automatically bound joinpoint is always named thisJoinPoint as all tutorials surely show you. Only in annotation-based syntax you need to bind the joinpoint and can name it as you wish, but even then I recommend to stick with thisJoinPoint because then refactoring from annotation to native syntax is easier and your eyes get used to spotting that variable name in your aspect code.
The warning you get means that the pointcut you defined does not match any part of your code, at least not any part which is visible to the aspect weaver or compiler. There could be plenty of reasons why this can occur, e.g. misspelled package or class names, wrong around advice return type (return type must be Object for non-void methods or more specifically match what the method you want to intercept returns). Assuming that e.g. checkUser(..) returns a boolean, the around advice should do the same. I made up an example using your package and class names. Besides, package names should be lower-case but I used yours, assuming they are really package names and not inner classes:
Helper class:
package com.example.UserAccount;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "User(" + name + ")";
}
}
Class targeted by aspect + sample main method:
package com.example.UserAccount;
public class MyUI {
public boolean checkUser(User user) {
return user.getName().toUpperCase().contains("ADMIN");
}
public static void main(String[] args) {
MyUI ui = new MyUI();
System.out.println(ui.checkUser(new User("Administrator")));
System.out.println(ui.checkUser(new User("john")));
System.out.println(ui.checkUser(new User("xander")));
System.out.println(ui.checkUser(new User("admiral")));
System.out.println(ui.checkUser(new User("SySaDmiN")));
}
}
As you can see, we expect an output of "true" for the first and last entry, but "false" for the ones in between due to the check logic I made up for checkUser(..).
Now let us write an aspect which also returns "true" for a user named "Xander", e.g. in order to give him admin rights or whatever. I am making this up because you did not provide an MCVE as you always should on StackOverflow, but just an incoherent code snippet which keeps everyone trying to answer your question guessing what the heck you might want to achieve and how to reproduce your problem.
Aspect:
package Aspects;
import com.example.UserAccount.User;
import com.example.UserAccount.MyUI;
public aspect UserAccount {
pointcut checkUser(User user) :
execution(boolean MyUI.checkUser(*)) && args(user);
boolean around(User user) : checkUser(user) {
System.out.println(thisJoinPoint + " -> " + user);
if (user.getName().equalsIgnoreCase("xander"))
return true;
return proceed(user);
}
}
I just imported the MyUI class, so there is no need to use a fully-qualified class name here. Again, this is an advantage of native syntax, in annotation-based syntax you would have to use the fully qualified name.
I also replaced the generic * MyUI.checkUser(..) (which would also work) by the more explicit boolean MyUI.checkUser(*) because we already know that the method returns a boolean and has exactly one parameter, which both we assume anyway by returning a boolean from the around advice and by binding exactly one parameter via args(). You could also be even more specific and use boolean MyUI.checkUser(User).
Furthermore, I am using execution() rather than call() because it is more efficient, as it weaves the advice code just into the executing method once instead of five times for each method call in the main method. You only need to use call() if the MyUI class is out of reach of the AspectJ weaver/compiler, i.e. because it is not in the module you compile with AspectJ Maven.
Console log:
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(Administrator)
true
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(john)
false
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(xander)
true
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(admiral)
false
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(SySaDmiN)
true
Et voilà, the aspect works. It makes the target method return "true" for user "xander".
I am using IntelliJ IDEA and I have problem with method usage finding.
Suppose I have interface Worker.
public interface Worker {
void startWork();
void endWork();
}
And I have two implementations.
public class Develper implements Worker {
#Override
public void startWork() {
System.out.println("Developer Start Working");
}
#Override
public void endWork() {
}
}
public class Qa implements Worker {
#Override
public void startWork() {
System.out.println("QA start Work");
}
#Override
public void endWork() {
}
}
I open the Developer class and trying to find usages of startWork().
I want only to view usage of the Developer.startWork() implemented method.
But when I find usages it shows both Developer and Qa.startWork() method usages. How can I avoid Qa.startWork() method usage when finding Developer.startWork() usages?
Using Ctrl+Shift+Alt+F7 (⌘+⇧+⌥+F7 for Mac) should show the prompt from Jim Hawkins answer.
See: https://www.jetbrains.com/help/idea/find-usages-method-options.html
When you search for usages of a method implementation with this dialog Ctrl+Shift+Alt+F7, IntelliJ IDEA will ask whether or not you want to search for the base method. With any other find usages actions such as Alt+F7 or Ctrl+Alt+F7, the base method will be included in the search results automatically.
I'm using IntelliJ IDEA 15.0.1 .
I think what you see when using the "find usages" functionality depends from the context.
If you place the cursor in method name Developer.startWork and invoke find usages , you should see a small dialog. You are asked "Do you want to find usages of the base method?" .
If you say "No", and in your sources you did only call the method via the base class or interface (Worker.start() in your example), IDEA doesn't show you any hits. Thats correct.
If you call the overridden method via Developer.startWork() , and press "No" in the dialog, then you will see the usages of the specific implementation.
Update:
After reading the answer from #JimHawkins, I think the elephant is still in the room :) The question is, do you want to see where Developer.startWork() is actually called, or do you want to see where it is statically referenced?
Eg:
Developer developer = new Developer();
developer.startWork(); // you want to find only this?
Worker worker = developer;
worker.startWork(); // ..or this as well?
The find usages method can only tell, where a given method is statically referenced, but not where it is actually used (that is determined runtime via the mechanism of polymorphism).
I'm wanting to use two custom matchers for a single method. Basically, if I pass the method VALUE_A, I want it to return RESULT_A, and if I pass it VALUE_B, I want it to return RESULT_B. So here's a code excerpt :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get()
//When this happens, the value of the get argument is null, so this method throws an NPE
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
class IsEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)));
}
}
[...]
//This line executes just fine
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult);
[...]
//This line calls IsNonEmpty.matches() for some reason. IsNonEmpty.matches() throws an NPE
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult);
When I assign the IsEmpty custom matcher to mockHTable.get() method, it calls the IsNonEmpty.matches() function. No idea why it's doing this. So I change the IsNonEmpty class to this :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher. Weird, no?
if(get == null) {
return false;
}
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
and then everything works just fine! IsNonEmpty.matches() is still called when I assign the IsEmpty matcher to the mockHTable.get() function, but my matchers work exactly how they should.
So what's the deal? Why does this happen? Is my work-around an adequate way to compensate for this quirky behavior, or am I Doing It Wrong?
The reason why IsNonEmpty.matches() gets called on the second line of stubbing is that the Mockito.argThat(new IsEmpty()) returns null, which is then passed to mockHTable.get(). This call has to be checked against the earlier stubbing, to see whether it's a match; and that means calling IsNonEmpty.matches().
I'm not sure why this makes your test fail - it's hard to tell without seeing all of the code.
But, I would seriously recommend using doReturn...when instead of when...thenReturn whenever you have to stub the same mock more than once. You won't encounter issues like this if you do. In fact, I prefer to use doReturn...when in preference to when...thenReturn always (and similarly doThrow and doAnswer), although most people prefer when...thenReturn.
Re-writing one of your stubbing lines with the doReturn...when syntax looks like the following. The other is similar.
Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty()));
Lastly, a plea, on behalf of the Mockito development team (of which I am a member). If you think there is a bug in Mockito here - and from your description, I think there may well be - please EITHER
send a message to the Mockito mailing group (mockito#googlegroups.com) OR
raise an issue on the Mockito issues list (http://code.google.com/p/mockito/issues/list).
It's useful to the Mockito team if you can actually post a complete example, rather than just what you think the key lines are - sometimes the cause of a Mockito problem is in quite an unexpected place.
I am using the org.eclipse.ui.popupMenus extension point for adding a sub-menu whose Action that is bounded to the following class:
public class MyAction implements IObjectActionDelegate {
private Logic logic = Logic.getInstance(); // Singleton
public void setActivePart(IAction a, IWorkbenchPart targetPart) {
// Nothing here
}
public void run(IAction a) {
// Do something...
}
public void selectionChanged(IAction a, ISelection s) {
a.setEnabled(logic.isEnabled(s));
}
}
This action is working correctly in most cases (including the call a.setEnabled() in selectionChanged()).
My problem at the very first time my action is being invoked. The selectionChanged method is called only after the menu item has been displayed (and not when the user has made the selection) which means that the call to a.setEnabled() will have no affect.
Any ideas on how to make my action receive selectionChanged() notifications even before the fist time it is being invoked?
Eclipse uses so-called lazy plugin activation, so it first derives as much as possible from plugin.xml, and the behaviour you are observing is well-documented in the API. See this related question.
The words first time and after make me wonder about a synchronization problem. If the initialization of Logic.getInstance() is deferred, you might look at the Initialization On Demand Holder Idiom, also discussed in item 71 of Effective Java.