JavaPsiScanner doesn't see calls - android-lint

I'm working on a custom Lint check and can't get all the method calls I need.
What I need: access to every add() call in lines like this:
Builder.from(arg)
.add(arg1, arg2)
.add(arg1, arg2)
.add(arg1, arg2);
What I get: visitMethod is not called at all. In such lines it's only called for 'from()'.
Detector code sample:
public class ExampleDetector extends Detector implements Detector.JavaPsiScanner {
#Override
public List<String> getApplicableMethodNames() {
return Collections.singletonList("add");
}
#Override
public void visitMethod(JavaContext context, #Nullable JavaElementVisitor visitor,
#NonNull PsiMethodCallExpression call, #NonNull PsiMethod method) {
...
}
....
}
How can I solve it? Why is it not visited at all?

Related

TestNG, is there a class level listener like IClassListener like ITestListener

I want to perform same action for every class (just like #BeforeClass). I guess listeners can do things where you don't have to write code individually, but I did not find in each method/class but can be executed via a listener. Is there a way to execute my method before every class or just once before method of that class?
Check the beforeConfiguration() method in TestListenerAdapter.
#Override
public void beforeConfiguration(ITestResult tr) {
if(tr.getMethod().getMethodName().equals("methodNameForBeforeClass")) {
//...
}
}
Try configuration related methods in TestListenerAdapter:
class TestNGListener extends TestListenerAdapter {
#Override
public void beforeConfiguration(ITestResult tr) {
super.beforeConfiguration(tr);
logger.info("=========== Configuration method '{}' started ===========", tr.getMethod().getMethodName());
}
#Override
public void onConfigurationSuccess(ITestResult tr) {
super.onConfigurationSuccess(tr);
logger.info("=========== Configuration method '{}' finished ===========", tr.getMethod().getMethodName());
}
#Override
public void onConfigurationFailure(ITestResult tr) {
super.onConfigurationFailure(tr);
logger.error("!!!!!!!!!!! Configuration method '{}' failed !!!!!!!!!!!", tr.getMethod().getMethodName());
}
}
Extend TestListenerAdapter and override onTestStart(ITestResult result) method. This will help you to run something everytime a test starts

error when adding GPS library admob

the error is :
The type AdListener cannot be a superinterface of FlyingPanda; a superinterface must be an interface
public class FlyingPanda extends Activity implements AdListener {
where is the problem i try to replace the implements kyeword by extends but the error still there.
need you help plz
According to the docs,
You can no longer implement AdListener from your Activity or class
You can use it as an anonymous inner class:
For Interstitial ads:
interstitalAd.setAdListener(new AdListener() {
public void onAdLoaded() {}
public void onAdFailedToLoad(int errorcode) {}
// Only implement methods you need.
});
And for banner ads
adView.setAdListener(new AdListener() {
public void onAdLoaded() {}
public void onAdFailedToLoad(int errorcode) {}
// Only implement methods you need.
});

In OOP reading from text file should be a Independent class method?

I have a class that only have main which read in some txt and do the algorithms.
my class is look like:
class doThejob{
public static void main(String args[]){
//*****start part A******
//do the reading from text file, and tokenize it
// process into the form I need,
//about 10-30 lines of codes
//******End of part A*****
//then run the algorithms
algorithm alg=new aglorithm();
Object output = alg.x(input);
//****Part B**** output to txt, about 10~40 lines
}
}
class algorithm{
private void a(Object x){
//do something
return (Object)result;
}
}
Can anyone tell me should I extract those part A and part B to a new class ,and then setup them as a public method .like below
class Io{
public Object readFromTxt(String path){
}
public void outputToTxt(String path){
}
}
And if I setup them , and then use it like below, is that more OOP?
class doThejob{
public static void main(String args[]){
Io dataProcess= new Io();
Object input = dataProcess.readFromTxt(args[0]);
algorithm alg=new aglorithm();
Object output =alg.x(input);
dataProcess.readFromTxt(args[1],output);
}
}
class algorithm{
private Object a(Object x){
//do something
}
}
Do it the way you fill is more readable.
Separating this in another class is according to the Single Responsability Principle. It will help making the code more readable and easy to change later on.
If you want to expand more on this, you could create an interface (eg.: IIO) for input and output. This way you can implement this interface in the IO class, renaming it to FileIO. Anytime you want to create another form of IO, like database access, you just have to create a DatabaseIO class that implements this interface and change the instance in the main method for this new type:
public interface IIO
{
string Read();
void Write(string text);
}
public class FileIO : IIO
{
string path;
public FileIO(string filePath)
{
path = filePath;
}
public string Read()
{
// read from file and return contents
}
public void Write(string text)
{
// write to file
}
}
public class SqlServerIO : IIO
{
SqlConnection conn;
public SqlServerIO(string connectionStringName)
{
// create the connection
}
public string Read()
{
// read from database
}
public void Write(string text)
{
// write to database
}
}
Extracting interfaces makes the code more maintenable by alowing to switch implementations anytime without messing with working code. It also facilitates unit testing.

how to pass context arguments to advice in spring aop

I am learning spring aop now,and I have no idea to pass context arguments to the advice.
Note I mean the context arguments,not the normal arguments.
It is simple to pass the normal arguments,for example:
a join point:
public void read(String something){
}
#Aspect
public class SessionAspect {
#Pointcut("execution(* *.*(String)) &&args(something)")
public void sess() {
}
#Before("sess()")
public void checkSessionExist(String something) {
//Here
}
}
Then the something argument will be passed to the the advice checkSessionExist.
But how about I want to get the context arguments like HttpSession or something else?
a join point:
public void listUser(){
dao.list(User.class,.....);
}
#Aspect
public class SessionAspect {
#Pointcut("execution(* *.*(String))")
public void sess() {
}
#Before("sess()")
public void checkSessionExist(String something) {
//Here
}
}
In this example,the listUser join point is only allowed for logined user.
So I want to check if there is a identify in the current HttpSession,so I need to get an instance of HttpSession at the advice checkSessionExist.
But how to get it?
The simplest way is to add the HttpSession argumets to all the joit points like this:
public void listUser(HttpSession session){
dao.list(User.class,.....);
}
However this have gone against the AOP it self. In my opinion,the join point even does not need to know the exist of the Aspect,isn't it?
How to fix it ?
Instead of passing HttpSession via #Pointcuts, you could fetch HttpSession reference in the #Aspect itself
RequestContextHolder.currentRequestAttributes()
.getAttribute("user", RequestAttributes.SCOPE_SESSION)
#Aspect
public class SessionAspect {
// fetch the current HttpSession attributes and use as required
private ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
#Pointcut("execution(* *.*(String))")
public void sess() {
}
#Before("sess()")
public void checkSessionExist(String something) {
//Here
}
}

Google Guice, Interceptors and PrivateModules

New poster here, hope I don't brake any rules :)
I am using PrivateModule in google-guice in order to have multiple DataSource's for the same environment. But I am having a hard time getting MethodInterceptor's to work inside the private modules.
Below is a simple test case that explains the "problem".
A simple service class would be:
interface Service {
String go();
}
class ServiceImpl implements Service {
#Override #Transactional
public String go() {
return "Test Case...";
}
}
The MyModule class would be:
class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new PrivateModule() {
#Override
protected void configure() {
bind(Service.class).to(ServiceImpl.class);
bindInterceptor(
Matchers.any(),
Matchers.annotatedWith(Transactional.class),
new MethodInterceptor() {
#Override
public Object invoke(MethodInvocation i)
throws Throwable {
System.out.println("Intercepting: "
+ i.getMethod().getName());
return i.proceed();
}
});
expose(Service.class);
}
});
}
}
And the final test case:
public class TestCase {
#Inject Service service;
public TestCase() {
Guice.createInjector(new MyModule()).injectMembers(this);
}
public String go() {
return service.go();
}
public static void main(String[] args) {
TestCase t = new TestCase();
System.out.println(t.go());
}
}
You would expect the output to be:
Intercepting: go
Test Case...
But it doesn't happen, the interceptor is not used, ant only Test Case... is output.
If I bind/expose the ServiceImpl instead of the interface then it works.
Thanks in advance,
Regards,
LL
Well... I figured it out shortly after I posted the question :)
The problem is that you also need to expose() the ServiceImpl class.
So the bind/expose would be.
bind(ServiceImpl.class); // ServiceImpl annotated with #Singleton
bind(Service.class).to(ServiceImpl.class);
expose(ServiceImpl.class);
expose(Service.class);
Regards,
LL
You need to explicitly bind ServiceImpl in the private module. The problem with your existing code is that it inherits the binding for ServiceImpl from the parent module. From the PrivateModule docs,
Private modules are implemented using parent injectors. When it can satisfy their dependencies, just-in-time bindings will be created in the root environment. Such bindings are shared among all environments in the tree.
Adding this line should fix the problem:
bind(ServiceImpl.class);