问题
Is it possible to use Checkstyle to forbid usage of some constructors or method that use system-dependent defaults (locale, charset, etc..). I prefer to enforce a policy where the programmer should be explicit about system-dependent values. So I consider the following items to be dangerous:
- all the constructors of
java.io.FielWriter
- using system-dependent encoding
- the
OutputStreamWriter(OutputStream os)
constructor ofjava.io.OutputStreamWriter
- using system-dependent encoding
- the
java.lang.String.toLowerCase()
method- using system default locale
- The
java.util.Calendar.getInstance()
method- using system default locale and default timezone
(the list goes on, you get the picture).
Is it possible to enforce this using Checkstyle 5.5?
回答1:
You can't do this by default. However, you can implement your own checker which checks for these methods.
The first option is to use Miscellaneous->Regexp. This is obviously only possible if you can find violations with a regexp. You will need to set illegalPattern = true. This would be a good place to start, I think.
The second options is to create your own check. See Writing Checks.
There are limitations to writing checkers. The first and most important is that you can't see other files. There isn't any cross checking. From the site:
- You cannot determine the type of an expression.
- You cannot see the content of other files. (although you can save processed files for use later)
This means that you cannot implement some of the code inspection features that are available in advanced IDEs like IntelliJ IDEA. For example you will not be able to implement a Check that finds redundant type casts or unused public methods.
So you couldn't check for instance that the java is calling one method which has an alternative with a Locale. You could use a blacklist of methods which you're not allowed to call. So for instance calls to new FileWriter() would check the number of parameters passed, or such like.
回答2:
I think an Annotation Processor would be more suitable to this task. From Matthew Farwell's answer "You cannot determine the type of an expression."
Assume you use a third party jar which contains class FancyWriter which extends FileWriter. You illegally put a x = new FancyWriter ( ) ;
in your code. CheckStyle will not find it because it is using regular expressions and it is not smart enough to know that FancyWriter is a FileWriter. I think you could write an annotation processor that figures out FancyWriter is really a FileWriter and is illegal.
OTH, someone - in theory - could write an extension of an illegal class that irons out the system dependency. For example, assume that FileWriter had a method in which it gets the system encoding. If LegalWriter extends FileWriter and override the method then we should not reject LegalWriter just b/c it extended an illegal class.
If you are using third party jars, how would their classes are legal. Just because they don't extend an illegal class, doesn't mean they don't use it. Then if you use one of their classes, your code is system dependent.
回答3:
As Matthew and emory stated, there isn't a perfect solution with check style. Here's my suggestion:
- Don't forbid only some constructors, but rather forbid all constructors of the affected classes. Then create your own subclass, which hides the forbidden constructors. For example create a checkstyle pattern "
FileWriter\(
" and a subclassSystemIndependentFileWriter
with only some of the super class' constructors. - Create the pattern "
toLowerCase()
" and hope, that nobody did create a method with the same name. Or use FindBugs to catch this one. - Create a checkstyle pattern "
Calendar.getInstance()
". I don't see a problem with that one.
Hopefully it will throw only a few false positives, which could be put on the ignore list. Eventually you need to tweak it to catch line breaks or other misplaced whitespaces.
来源:https://stackoverflow.com/questions/8416870/checkstyle-rule-to-prevent-invocation-of-some-methods-and-constructors