Bug 318682 - Enhancement request: Warning if no fields are used and the method is still not static
Summary: Enhancement request: Warning if no fields are used and the method is still no...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: PC Windows Server 2003
: P3 enhancement (vote)
Target Milestone: 3.7 M5   Edit
Assignee: Ayushman Jain CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 40536 (view as bug list)
Depends on:
Blocks: 331577
  Show dependency tree
 
Reported: 2010-07-02 05:40 EDT by Lars Svensson CLA
Modified: 2011-01-25 10:54 EST (History)
9 users (show)

See Also:
satyam.kandula: review+


Attachments
proposed fix v1.0 + regression tests + doc (52.07 KB, patch)
2010-10-06 15:08 EDT, Ayushman Jain CLA
no flags Details | Diff
proposed fix v1.1 + regression tests + doc (34.95 KB, patch)
2010-10-16 16:11 EDT, Ayushman Jain CLA
no flags Details | Diff
proposed fix v1.1.2 + regression tests (52.08 KB, patch)
2010-10-18 07:28 EDT, Ayushman Jain CLA
no flags Details | Diff
proposed fix v1.2 + regression tests (65.06 KB, patch)
2010-11-19 01:19 EST, Ayushman Jain CLA
no flags Details | Diff
proposed fix v1.3 + regression tests (45.76 KB, patch)
2010-12-01 07:41 EST, Ayushman Jain CLA
no flags Details | Diff
proposed fix v1.4 + regression tests (75.11 KB, patch)
2010-12-06 04:06 EST, Ayushman Jain CLA
no flags Details | Diff
fix 1.4 with cosmetic changes + tests (76.50 KB, patch)
2010-12-16 15:16 EST, Ayushman Jain CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Lars Svensson CLA 2010-07-02 05:40:07 EDT
Build Identifier: 

I would like an option under Compiler-> Errors/Warnings that said "Methods that could be static" ot something.

If a method is using no fields and no calls to non-static functions it could and should be set as a static method. Would like some hints on how to find these methods. 

Reproducible: Always
Comment 1 Lars Svensson CLA 2010-07-02 05:51:41 EDT
This is my last report for a while.

I have summerized one year of notations of possible bugs and enhanchment suggestions and got some time from my Company SAAB to check all these notations in new releases.

I now have 19 reports listed and I am already amazed about how fast I get response, support and feedback.

Thank you very much Eclipse Team!
Comment 2 Walter Harley CLA 2010-07-04 02:43:12 EDT
Thanks for all your suggestions, Lars!  By the way, if you have more and you are able, please try to set the component, as well as the project.  You've reported them against the "APT" component, which is the Annotation Processing Tooling, which I think was not your intention.

With regard to this present suggestion, I agree that would be a good feature.  One thing you might want to do is install the FindBugs plugin, which will identify this problem as well as many others.  I highly recommend it.
Comment 3 Ayushman Jain CLA 2010-07-05 03:16:23 EDT
Sounds interesting. Will see what it takes.
Comment 4 Ayushman Jain CLA 2010-10-06 15:08:30 EDT
Created attachment 180366 [details]
proposed fix v1.0 + regression tests + doc

This fix introduces the new option JavaCore.COMPILER_PB_METHOD_CAN_BE_STATIC and the new problem org.eclipse.jdt.core.compiler.IProblem.MethodCanBeStatic. The way it is implemented is as follows:
We first mark every non-abstract, non-empty method as potentially static using the new bit ASTNode.CanBeStatic. This is done in MethodDeclaration#resolveCode().

Susequently, when each statement of the method is analysed in org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.analyseCode(ClassScope, InitializationFlowContext, FlowInfo), we check for references to non-static fields and methods. This can be in the form of 
- field reference:
   ...
    abc = this.field;    (#analyseCode(..))
   ...
   or
   ...
    this.field = 1;      (#analyseAssignment)
   ...
- QualifiedNameReference:
  ...
   abc = X.field;
  ...
  or
  ...
   X.field = 1;
  ...

- SingleNameReference:
  ...
   abc = field;
  ...
  or
  ...
   field = 1;
  ...

- MessageSend:
  ...
   method1();
  ...
  or
  ...
   this.method1();
  ...
 or
 ...
   X.method1();
 ...

etc.

Basically, since "this" reference is never allowed in static methods, we mark the method as cannot be static if we come across any explicit this reference. (Note that just referencing a method without a receiver viz. method1(), contains an implicit this reference, but this is allowed in static methods). For statements with no this receiver, we just need to check if its a non-static field/method.  Tests added in org.eclipse.jdt.core.tests.compiler.regression.ProblemTypeAndMethodTest show different cases of how a method/field could be referenced.
Comment 5 Ayushman Jain CLA 2010-10-06 15:09:49 EDT
Satyam, please review. TIA
Comment 6 Ayushman Jain CLA 2010-10-11 02:39:50 EDT
The above patch introduces a new warning "The method {1}({2}) from the type {0} can be declared as static". There are a few aesthetic points pointed out by Satyam that we should probably decide upon:

- With this patch, the warning is raised even for methods that override a superclass method and methods that are overriden in subclasses. While for the former cases, we can and we should hide the warning, its not possible to do so in the latter case since we dont have the info about a method's overriders. Is it ok to show the warning in the latter case as well? IMO, its safe to show the warning since it only says "the method can be static"

- Should we have just one warning or two warnings saying "should be static" and "potentially static"? In case a class is final, or method is private and the method has passes the analysis to be declared static, we can say with surety that it should be static since it cant be overriden. While in other cases, including the case pointed out in the previous comment, we are not 100% sure since the method may be overriden.

Olivier, what's your opinion about these points?
Comment 7 Ayushman Jain CLA 2010-10-16 16:11:43 EDT
Created attachment 181037 [details]
proposed fix v1.1 + regression tests + doc

This patch adds a small change to the previous one- for overriding/implementing methods we dont raise this warning.
Comment 8 Ayushman Jain CLA 2010-10-18 07:28:05 EDT
Created attachment 181082 [details]
proposed fix v1.1.2 + regression tests

Somehow the previous patch did not contain all the changed files. 
Submitting a fresh patch with all changes
Comment 9 Markus Keller CLA 2010-10-18 10:58:41 EDT
*** Bug 40536 has been marked as a duplicate of this bug. ***
Comment 10 Ayushman Jain CLA 2010-10-18 11:21:04 EDT
Markus, it'll be good to have your opinion as well on the points in comment 6.
Comment 11 Markus Keller CLA 2010-10-18 12:20:31 EDT
(In reply to comment #6)
> In case a class is final, or method is private and the
> method has passes the analysis to be declared static, we can say with surety
> that it should be static since it cant be overriden. While in other cases,
> including the case pointed out in the previous comment, we are not 100% sure
> since the method may be overriden.

That's IMO a reason for not adding this "potential" problem. As stated in bug
101849 comment 4, we don't have the infrastructure to find overriding methods
efficiently, so this will lead to false positives. And if we add a quick fix,
people will rightfully complain that we offer bad advice and the quick fix
screws their code.

If we add this, then we should have two options (similar to "Null pointer
access" and "Potential null pointer access"), such that people can at least
disable the one that reports false positives. And someone would have to come up
with good names for the options.


(In reply to comment #8)
> Created an attachment (id=181082) [details] [diff]
> proposed fix v1.1.2 + regression tests

Typo in Javadoc and help: "a method has not be declared": "be" => "been".
Comment 12 Satyam Kandula CLA 2010-10-19 07:18:00 EDT
Patch generally looks good. Here are some points to consider. 
1. I think empty methods should not be flagged to be static. These are probably in place so that the sub types could override the behavior. 
2. As Olivier had mentioned, the message probably can be improved which could indicate that it is not completely sure. Well, I don't have a better message as of now.
3. Having a problem with local classes using the outer class's variable. In the given test case foo should not have been reported as can be static. 
            public class Test {
              public String name;
              public void foo() {
		(new Object() {
			public boolean foo1() {
				return Test.this.name == null;
		}
		}).foo1();
		return;
             }
	   } 
4. If a method uses Type parameters of the given type, that method probably cannot be static.
5. Accesses to super also have to be taken care.  
6. In ASTNode.java, CanBeStatic should be declared under the comment for method declaration. Right now, it is declared under the comment type, method and field. As this field is for only methods, it should be declared elsewhere.
Comment 13 Olivier Thomann CLA 2010-10-19 11:33:13 EDT
Discussing with Markus, since we cannot properly detect the case where a method is overriden in subclass, this check will lead to too many false positives.
So we think we should not continue to investigate this issue and close as WONTFIX.
Ayushman, do you agree with this ?
Comment 14 Ayushman Jain CLA 2010-10-20 01:33:09 EDT
(In reply to comment #13)
> Discussing with Markus, since we cannot properly detect the case where a method
> is overriden in subclass, this check will lead to too many false positives.
> So we think we should not continue to investigate this issue and close as
> WONTFIX.
> Ayushman, do you agree with this ?

I dont think we should just give up. I discussed with Satyam and Srikanth as well.
There are 2 things here that we need to consider:
1. SHOULD BE STATIC: Methods that are private, or final, or inside a final class, cannot be overriden at all. So atleast in these cases we're sure that if a method passes our analysis to be static, we can and should emit this warning, and maybe make it more concrete to say the method should be marked as static.

2. POTENTIALLY STATIC: These are the cases in which we dont know whether a method is being overriden. Even in these cases I think we should emit a warning, but change the wording a bit. The basic idea is that this is not really a compilation error, but a compiler suggestion to improve code aesthetics. I have seen many developers just care about writing a working code, and aesthetics take the last priority. So in some case where a developer has unintentionally missed out declaring a method as static, this suggestion will atleast alert him. To have a warning which says "The method ... can be declared as static, if it is not overriden elsewhere" (or something similar), will be good and will not be a "false positive" per se! The user can atleast look at the warning and decide to exercise the quick fix *IF* he wants.
Comment 15 Ayushman Jain CLA 2010-10-21 03:20:06 EDT
(In reply to comment #14)
> [..]
Olivier/Markus, please let me know your opinion. If the suggested changes seem viable, i'll submit a fresh patch incorporating them. 

As for the names, how do
COMPILER_PB_METHOD_POTENTIALLY_STATIC, and COMPILER_PB_METHOD_SHOULD_BE_STATIC sound?
Comment 16 Markus Keller CLA 2010-10-21 09:10:11 EDT
OK, we can do it if the options are split into a reliable one and a potential hint. But I don't want to rush it into M3, and UI needs more time to add the quick fixes and a Clean Up for the safe option.

> As for the names, how do
> COMPILER_PB_METHOD_POTENTIALLY_STATIC, and COMPILER_PB_METHOD_SHOULD_BE_STATIC
> sound?

Please look at the options we already have. The options names should be more modest and describe what problems they find (and not prescribe a solution using works like "should").
Comment 17 Ayushman Jain CLA 2010-10-22 07:24:53 EDT
(In reply to comment #16)
> Please look at the options we already have. The options names should be more
> modest and describe what problems they find (and not prescribe a solution using
> works like "should").

Hmm. How about COMPILER_PB_MISSING_STATIC_ON_METHOD, and COMPILER_PB_POTENTIAL_MISSING_STATIC_ON_METHOD ? This is on the lines of COMPILER_PB_MISSING_SYNCHRONIZED_ON_INHERITED_METHOD.
Comment 18 Markus Keller CLA 2010-10-22 09:11:50 EDT
COMPILER_PB_MISSING_STATIC_ON_METHOD sounds good.

The second was grammatically wrong and should rather be: COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD.
Comment 19 Stephan Herrmann CLA 2010-11-18 19:08:31 EST
I know I'm late to this party, so let my comment not stop you, but ...

(In reply to comment #14)
> The basic idea is that this is not
> really a compilation error, but a compiler suggestion to improve code
> aesthetics. 

IMHO this is strange quality metric. Put bluntly, I would read that warning as:
"you are using object-oriented programming, but we advise you not to do so."

Sure there are potential reasons for marking a method as static:
(a) To be able to call it if you don't have an instance
(b) To make sure you can read and understand the code without considering
    dynamic binding
(c) To make the code faster.

For (a) you don't need a warning, as you will find the need yourself.
Arguing along (c) you're trying to compete with the JVM and its JIT.
Do we definitely know that the JVM needs the 'static' mark to avoid dynamic
dispatch? Only (b) seems to really help some people who are not used to 
reading object-oriented code (who use F3 instead of Ctrl-t :) )

Anyway, due to (b) I admit it is a matter of taste and since I don't have
to enable the warning I won't mind it. 

BTW: Has it been considered to offer a *refactoring* for this (which would 
then check hierarchies up AND down)? Perhaps as part of change method
signature? Or is the change too trivial for that?
Comment 20 Ayushman Jain CLA 2010-11-19 01:19:07 EST
Created attachment 183447 [details]
proposed fix v1.2 + regression tests

This patch basically follows the same logic as in the above patch, except for a few changes:
1. Changed the name of the option(s) in JavaCore. There are now 2 options - COMPILER_PB_MISSING_STATIC_ON_METHOD and COMPILER_PB_POTENTIALLY_MISSING_STATIC_ON_METHOD. Updated the documentation and the guide as well.
2. Changed the position of the declared bit CanBeStatic in ASTNode according to point 6 in satyam's comment.
3. Handling super reference case now, with the changes in org.eclipse.jdt.internal.compiler.ast.SuperReference.
4. Making sure that local type's methods are not warned for. (Changes in MethodDeclaration.java:233 onwards).
5. Making sure that we dont warn for empty methods. (Changes in line MethodDeclaration.java:102).
6. Making sure that methods using type parameters declared by enclosing class arent warned for. (Changes in line MethodDeclaration.java:84 onwards)
7. Changed the method org.eclipse.jdt.internal.compiler.lookup.BlockScope.resetEnclosingMethodStaticFlag() to include the case of local type's method accessing a field of the outer type. (point no. 3 in satyam's comment).
8. Added more tests in ProblemTypeAndMethodTest.java

Satyam, please review. Thanks!
Comment 21 Ayushman Jain CLA 2010-11-19 01:32:27 EST
(In reply to comment #19)
> I know I'm late to this party, so let my comment not stop you, but ...
>[..]

I guess the motivation behind this warning is not really to show any potential problem in the code, but to suggest an alternative way of writing that same code, which would result in more efficiency overall. This would happen if, say, a programmer doesn't declare a method as static, and just to call the method at many places, instantiates an object of the class. (Most coders won't do such a mistake, but a few can when they're running on caffeine overdose! ;) ). In that case, just to call a method, a lot of memory ends up getting wasted in just instantiating objects. This atleast could have been prevented if the method was declared static.

The new warning is also on the lines of other "code style" warnings that you see in Java>Compiler>Errors/warnings, viz. "Undocumented empty block", "non static access to static member", etc. - all of which are not programming errors per se. 

I wouldn't introduce this warning if it were expensive to analyse the code for it. But as you can see in the attached patch, there's minimal overhead in raising this warning, so i think there's no harm in introducing it! :)
Comment 22 Olivier Thomann CLA 2010-11-29 15:17:10 EST
Not sure we want this warning on by default.
Comment 23 Satyam Kandula CLA 2010-11-30 22:54:30 EST
Sorry for the late review.. Overall, it looks good except for some minor
comments. As Olivier had mentioned, I also think this warning should be turned off by default. 

1. Main.java: Why is there only one option for both potential and normal error?
I think here also there should be two options. What do you think?
2. MethodDeclaration.java: A comment could help when the flag is turned off for
empty  body..
3. MethodDeclaration.java: There is a comment telling that the methods should
not be static for local types and then I see this line. this.bits |=
ASTNode.CanBeStatic; Am I missing something? 
4. Though you have fixed the problem where methods could take type arguments of
the given class, the method statements or the return type could also refer to
the type parameter of the class. In this case also, static warning should be
returned. 
Eg: class X <T> { void foo() { T a;} }
Comment 24 Ayushman Jain CLA 2010-12-01 07:41:28 EST
Created attachment 184249 [details]
proposed fix v1.3 + regression tests

Done.

As for the comment in MethodDeclaration, I think it was just confusing, so I changed the wording, the code otherwise is correct.
Also added the test for usage of type parameter in ProblemTypeAndMethodTest.test120().
Comment 25 Markus Keller CLA 2010-12-01 08:19:08 EST
(In reply to comment #24)
> Created an attachment (id=184249) [details] [diff]
> proposed fix v1.3 + regression tests

This patch is incomplete (e.g. misses JavaCore and DefaultCodeFormatter).


(In reply to comment #11)
> Typo in Javadoc and help: "a method has not be declared": "be" => "been".

Still not fixed in the patch from comment 20.


Note that I will not have time to add the UI for this for M4 (I don't want to add the preference options without offering the corresponding quick fixes).
Comment 26 Olivier Thomann CLA 2010-12-01 09:47:09 EST
(In reply to comment #25)
> Note that I will not have time to add the UI for this for M4 (I don't want to
> add the preference options without offering the corresponding quick fixes).
So this should be moved to M5 all together. Early in M5 looks like a good timing then.
Comment 27 Satyam Kandula CLA 2010-12-01 10:08:33 EST
MethodDeclaration is also not part of the patch. 

Here are some quick comments in LocalDeclaration.java: 
   1. Probably many computations could be avoided if there is a check of the
method not being static yet. 
   2. You would want to remove those code you had commented.
   3. There is a problem in the for loop. If the first type parameter doesn't
match, it just marks it static.
Comment 28 Ayushman Jain CLA 2010-12-02 02:04:33 EST
(In reply to comment #25)
> (In reply to comment #24)
> > Created an attachment (id=184249) [details] [diff] [details] [diff]
> > proposed fix v1.3 + regression tests
> 
> This patch is incomplete (e.g. misses JavaCore and DefaultCodeFormatter).
> 
> 
> (In reply to comment #11)
> > Typo in Javadoc and help: "a method has not be declared": "be" => "been".
> 
> Still not fixed in the patch from comment 20.
> 
> 
> Note that I will not have time to add the UI for this for M4 (I don't want to
> add the preference options without offering the corresponding quick fixes).

CVS is my nemesis! I dont know why it missed out these files in the patch! :)
I'll recreate the patch and also take care of Satyam's comments.
Comment 29 Markus Keller CLA 2010-12-02 05:54:59 EST
(In reply to comment #28)
> CVS is my nemesis! I dont know why it missed out these files in the patch! :)
> I'll recreate the patch and also take care of Satyam's comments.

It's probably not CVS, but the Eclipse CVS Team Provider. Please yell in
bug 294650.
Comment 30 Ayushman Jain CLA 2010-12-06 04:06:59 EST
Created attachment 184577 [details]
proposed fix v1.4 + regression tests

This patch adds another check to make sure that if the method returns a type parameter not declared by it, the new warning isnt raised (added ProblemTypeAndMethodTest.test123() for it).
Comment 31 Ayushman Jain CLA 2010-12-16 15:16:40 EST
Created attachment 185363 [details]
fix 1.4 with cosmetic changes + tests

Same fix as above, but changed ASTNode$canBeStatic from bit 6 to bit 9, and shortened the name of a few locals.
Comment 32 Satyam Kandula CLA 2010-12-17 01:33:41 EST
Changes look good for me. +1 for this
Comment 33 Ayushman Jain CLA 2010-12-17 04:39:20 EST
Released in HEAD for 3.7M5
Comment 34 Srikanth Sankaran CLA 2011-01-25 10:54:56 EST
Verified for 3.7 M5 using build id: I20110124-1800