mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
import
This commit is contained in:
371
plugins/InspectionGadgets/Announcement
Normal file
371
plugins/InspectionGadgets/Announcement
Normal file
@@ -0,0 +1,371 @@
|
||||
|
||||
Announcing version 1.0 of the InspectionGadgets plugin, available via the PluginManager
|
||||
or at http://www.intellij.org/twiki/bin/view/Main/InspectionGadgets.
|
||||
|
||||
Changes in version 1.0
|
||||
|
||||
New inspections:
|
||||
|
||||
* Use of '$' in identifier
|
||||
* Infinite Recursion
|
||||
* Auto-Boxing
|
||||
* Auto-Unboxing
|
||||
* Unnecessary boxing
|
||||
* Unnecessary unboxing
|
||||
* Class without no-arg constructor
|
||||
* Unnecessary 'final' for method parameter
|
||||
* Unnecessarily qualified static method call
|
||||
* Unqualified static method call
|
||||
* setUp() with incorrect signature
|
||||
* tearDown() with incorrect signature
|
||||
* setUp() doesn't call super.setUp()
|
||||
* tearDown() doesn't call super.tearDown()
|
||||
* Test method with incorrect signature
|
||||
* 'assert' statement
|
||||
* Use of 'enum' as identifier
|
||||
|
||||
plus huge numbers of bugfixes.
|
||||
|
||||
Special thanks go to Bas Lejsdekkers and Keith Lea for their help and ideas on this release.
|
||||
|
||||
With the 1.0 release, development on InspectionGadgets will be going into "bugfixes-only"
|
||||
mode for the next several months. Thanks to everyone for your ideas, code, and
|
||||
criticism as I developed InspectionGadgets. It's thanks to your interest and support
|
||||
that InspectionGadgets has become the most full-featured and powerful Java static analysis
|
||||
tool available today, and the most-downloaded IDEA plugin. I hope I've helped you kill a
|
||||
lot of bugs.
|
||||
|
||||
|
||||
|
||||
|
||||
* Abstraction issues
|
||||
* Cast to a concrete class
|
||||
* Class references one of its subclasses
|
||||
* Collection declared by class, not interface
|
||||
* Concrete class for instance variable
|
||||
* Concrete class for local variable
|
||||
* Concrete class for method parameter
|
||||
* Concrete class for method return
|
||||
* Concrete class for static variable
|
||||
* 'instanceof' a concrete class
|
||||
* "Magic number"
|
||||
* 'switch' statement
|
||||
|
||||
* Class metrics
|
||||
* Class too deep in inheritance tree
|
||||
* Class with too many constructors
|
||||
* Class with too many fields
|
||||
* Class with too many methods
|
||||
* Inner class too deeply nested
|
||||
* Overly complex class
|
||||
* Overly coupled class
|
||||
|
||||
* Class structure
|
||||
* Abstract class extends concrete class
|
||||
* Abstract class without abstract methods
|
||||
* Abstract method overrides abstract method
|
||||
* Abstract method overrides concrete method
|
||||
* Class may be interface
|
||||
* Class without constructor
|
||||
* Class without no-arg constructor
|
||||
* Class without package statement
|
||||
* Constant declared in abstract class
|
||||
* Constant declared in interface
|
||||
* constructor not 'protected' in 'abstract' class(*)
|
||||
* 'final' method in 'final' class(*)
|
||||
* Inner class of interface
|
||||
* No-op method in abstract class
|
||||
* 'private' method declared 'final'(*)
|
||||
* 'protected' member in 'final' class(*)
|
||||
* 'public' constructor in non-'public' class(*)
|
||||
* Static inheritance
|
||||
* 'static' method declared 'final'(*)
|
||||
* 'static', non-'final' field
|
||||
* Utility class
|
||||
* Utility class with public constructor
|
||||
* Utility class without private constructor
|
||||
|
||||
* Cloning issues
|
||||
* clone() doesn't call super.clone()
|
||||
* clone() doesn't declare CloneNotSupportedException
|
||||
* clone() instantiates objects with constructor
|
||||
* Cloneable class without 'clone()'
|
||||
|
||||
* Code maturity issues
|
||||
* Call to printStackTrace()
|
||||
* Call to Thread.dumpStack()
|
||||
* Class without toString()
|
||||
* Use of obsolete collection type
|
||||
* Use of System.out or System.err
|
||||
|
||||
* Code style issues
|
||||
* C-style array declaration(*)
|
||||
* Constant on left side of comparison(*)
|
||||
* Constant on right side of comparison(*)
|
||||
* expression.equals("literal") rather than "literal".equals(expression)(*)
|
||||
* Missorted modifers(*)
|
||||
* Multiple variables in one declaration(*)
|
||||
* Return of 'this'
|
||||
* Unnecessarily qualified static method call(*)
|
||||
* Unqualified static method call(*)
|
||||
* Variables of different types in one declaration(*)
|
||||
|
||||
* Encapsulation issues
|
||||
* Assignment to Collection or array field from parameter
|
||||
* Package-visible field
|
||||
* Package-visible inner class
|
||||
* Protected field
|
||||
* Protected inner class
|
||||
* Public field
|
||||
* Public inner class
|
||||
* Return of Collection or array field
|
||||
|
||||
* Error handling
|
||||
* 'catch' generic class
|
||||
* Checked exception class
|
||||
* Empty 'catch' block
|
||||
* Empty 'finally' block
|
||||
* Empty 'try' block
|
||||
* Error not rethrown
|
||||
* 'instanceof' on 'catch' parameter
|
||||
* Nested 'try' statement
|
||||
* Overly broad 'catch' block
|
||||
* 'return' inside 'finally' block
|
||||
* ThreadDeath not rethrown
|
||||
* 'throw' generic class
|
||||
* 'throw' inside 'catch' block which ignores the caught exception
|
||||
* 'throw' inside 'finally' block
|
||||
* Unchecked exception class
|
||||
|
||||
* Finalization issues
|
||||
* finalize() called explicitly
|
||||
* finalize() doesn't call super.finalize()
|
||||
* finalize() not declared 'protected'(*)
|
||||
* Use of finalize()
|
||||
|
||||
* Imports
|
||||
* * import
|
||||
* Import from same package
|
||||
* java.lang import
|
||||
* Redundant import
|
||||
* Single class import
|
||||
* Unused import
|
||||
|
||||
* Initialization issues
|
||||
* Abstract method call in constructor
|
||||
* Instance variable may not be initialized
|
||||
* Overridable method call in constructor
|
||||
* Static variable may not be initialized
|
||||
|
||||
* Internationalization issues
|
||||
* Call to Date.toString()
|
||||
* Call to Numeric .toString()
|
||||
* Call to String.compareTo()
|
||||
* Call to String.equals()
|
||||
* Call to String.equalsIgnoreCase()
|
||||
* Call to Time.toString()
|
||||
* Character comparison
|
||||
* Hardcoded string literal
|
||||
* "Magic character"
|
||||
* String concatenation
|
||||
* Use of StringTokenizer
|
||||
|
||||
* JUnit issues
|
||||
* JUnit TestCase with non-trivial constructors
|
||||
* Missing message on JUnit assertion
|
||||
* setUp() doesn't call super.setUp()
|
||||
* setUp() with incorrect signature
|
||||
* 'setup()' instead of 'setUp()'(*)
|
||||
* 'suite()' method not declared 'static'
|
||||
* tearDown() doesn't call super.tearDown()
|
||||
* tearDown() with incorrect signature
|
||||
* 'teardown()' instead of 'tearDown()'(*)
|
||||
* Test method with incorrect signature
|
||||
|
||||
* Method metrics
|
||||
* Method with more than three negations
|
||||
* Method with multiple loops
|
||||
* Method with multiple return points.
|
||||
* Method with too many parameters
|
||||
* Overly complex method
|
||||
* Overly coupled method
|
||||
* Overly long method
|
||||
* Overly nested method
|
||||
|
||||
* Naming conventions
|
||||
* Class name prefixed with package name(*)
|
||||
* Class naming convention(*)
|
||||
* Confusing 'main()' method(*)
|
||||
* Constant naming convention(*)
|
||||
* Exception class name doesn't end with Exception(*)
|
||||
* Instance method naming convention(*)
|
||||
* Instance variable naming convention(*)
|
||||
* Interface naming convention(*)
|
||||
* Local Variable naming convention(*)
|
||||
* Method name same as class name(*)
|
||||
* Method name same as parent class name(*)
|
||||
* Method parameter naming convention(*)
|
||||
* Non-exception class name ends with 'Exception'(*)
|
||||
* Standard variable names(*)
|
||||
* Static method naming convention(*)
|
||||
* Static variable naming convention(*)
|
||||
* Use of '$' in identifier(*)
|
||||
|
||||
* Performance issues
|
||||
* Boolean constructor call(*)
|
||||
* Calls to System.gc() or Runtime.gc()
|
||||
* Collection without initial capacity
|
||||
* Field may be 'static'(*)
|
||||
* Field repeatedly accessed in method
|
||||
* Manual array copy(*)
|
||||
* Multiply or divide by power of two(*)
|
||||
* Object allocation in loop
|
||||
* Redundant String constructor call(*)
|
||||
* Redundant String.toString()(*)
|
||||
* Single character .startsWith() or .endsWith()
|
||||
* Single character string concatenation(*)
|
||||
* Static collection
|
||||
* String concatenation in loop
|
||||
* StringBuffer without initial capacity
|
||||
* StringBuffer.toString() in concatenation(*)
|
||||
* Tail recursion
|
||||
* Unnecessary temporary object in conversion from String(*)
|
||||
* Unnecessary temporary object in conversion to String(*)
|
||||
* Use of java.lang.reflect
|
||||
* Zero-length array allocation
|
||||
|
||||
* Portability issues
|
||||
* 'assert' statement
|
||||
* Auto-boxing(*)
|
||||
* Auto-unboxing(*)
|
||||
* Call to Runtime.exec()
|
||||
* Call to System.exit()
|
||||
* Call to System.getenv()
|
||||
* Hardcoded file separator
|
||||
* Hardcoded line separator
|
||||
* Native method
|
||||
* Use of 'assert' as identifier(*)
|
||||
* Use of 'enum' as identifier(*)
|
||||
|
||||
* Potentially confusing code constructs
|
||||
* Assignment to for-loop parameter
|
||||
* Assignment to method parameter
|
||||
* 'break' statement
|
||||
* 'break' statement with label
|
||||
* Chained equality comparisons
|
||||
* Chained method calls
|
||||
* Conditional expression (?:)
|
||||
* Confusing else branch
|
||||
* Confusing floating-point literal(*)
|
||||
* 'continue' statement
|
||||
* 'continue' statement with label
|
||||
* If statement with negated condition
|
||||
* Implicit call to super()(*)
|
||||
* Implicit numeric conversions(*)
|
||||
* Local variable used and declared in different 'switch' branches
|
||||
* Long literal ending with 'l' instead of 'L'(*)
|
||||
* Method names differing only by case
|
||||
* Nested 'switch' statement
|
||||
* Nested assignment
|
||||
* Nested conditional expression
|
||||
* Nested method calls
|
||||
* Numeric cast that loses precision
|
||||
* Overloaded methods with same number of parameters
|
||||
* Overly complex arithmetic expression
|
||||
* Overly complex boolean expression
|
||||
* Switch statement with too few branches
|
||||
* Switch statement with too many branches
|
||||
* Value of ++ or -- used
|
||||
|
||||
* Probable bugs
|
||||
* Assignment to 'null'
|
||||
* Assignment used as condition
|
||||
* 'compareto()' instead of 'compareTo()'(*)
|
||||
* Comparison of short and char values
|
||||
* Covariant compareTo()
|
||||
* Covariant equals()
|
||||
* 'default' not last case in 'switch'
|
||||
* equals() between objects of inconvertible types
|
||||
* Fallthrough in 'switch' statement
|
||||
* Floating point equality comparison
|
||||
* For loop where update or condition doesn't use loop variable
|
||||
* For loop with missing components
|
||||
* 'hashcode()' instead of 'hashCode()'(*)
|
||||
* Infinite loop statement
|
||||
* Infinite recursion
|
||||
* Loop statement that doesn't loop
|
||||
* Non-final field referenced in 'compareTo()'
|
||||
* Non-final field referenced in 'equals()'
|
||||
* Non-final field referenced in 'hashCode()'
|
||||
* Object comparison using ==, instead of '.equals()'(*)
|
||||
* Octal and decimal integers in same array
|
||||
* Result of InputStream.read() ignored
|
||||
* Return of 'null'
|
||||
* Statement with empty body
|
||||
* String comparison using ==, instead of '.equals()'(*)
|
||||
* Subtraction in compareTo()
|
||||
* 'switch' statement without 'default' branch
|
||||
* Text label in 'switch' statement
|
||||
|
||||
* Security issues
|
||||
* Cloneable class in secure context
|
||||
* Deserializable class in secure context
|
||||
* Non-static inner class in secure context
|
||||
* Serializable class in secure context
|
||||
|
||||
* Serialization issues
|
||||
* Instance variable may not be initialized by readObject
|
||||
* Non-serializable class with 'readObject()' or 'writeObject()'
|
||||
* Non-serializable class with serialVersionUID
|
||||
* 'readObject()' or 'writeObject()' not declared 'private'(*)
|
||||
* 'readResolve()' or 'writeReplace()' not declared 'protected'(*)
|
||||
* Serializable class with unconstructable ancestor
|
||||
* Serializable class without 'readObject()' and 'writeObject()'
|
||||
* Serializable class without serialVersionUID
|
||||
* 'serialVersionUID' field not declared 'static final'(*)
|
||||
* Transient field in non-serializable class(*)
|
||||
|
||||
* Threading issues
|
||||
* Busy wait
|
||||
* Call to notify() instead of notifyAll()(*)
|
||||
* Call to Thread.run()(*)
|
||||
* Double-checked locking
|
||||
* Empty 'synchronized' statement
|
||||
* Field accessed in both synchronized and unsynchronized contexts
|
||||
* Nested 'synchronized' statement
|
||||
* Non-private field accessed in synchronized context
|
||||
* Non-synchronized method overrides synchronized method
|
||||
* Synchronization on 'this'
|
||||
* Synchronization on a non-final field
|
||||
* 'synchronized' method
|
||||
* 'wait()' not in loop
|
||||
|
||||
* Verbose or redundant code constructs
|
||||
* Assignment replacable with operator assignment(*)
|
||||
* Class explicitly extends java.lang.Object
|
||||
* 'for' loop may be replaced by 'while' loop(*)
|
||||
* Pointless arithmetic expression(*)
|
||||
* Redundant boolean comparison(*)
|
||||
* Redundant field initialization(*)
|
||||
* Unnecessary 'final' for method parameter(*)
|
||||
* Unnecessary 'if' statement(*)
|
||||
* Unnecessary 'return' statement(*)
|
||||
* Unnecessary 'super()' statement(*)
|
||||
* Unnecessary 'this' qualifier(*)
|
||||
* Unnecessary boxing(*)
|
||||
* Unnecessary code block(*)
|
||||
* Unnecessary fully qualified name(*)
|
||||
* Unnecessary interface modifier(*)
|
||||
* Unnecessary parentheses(*)
|
||||
* Unnecessary semicolon(*)
|
||||
* Unnecessary unboxing(*)
|
||||
* Unused label(*)
|
||||
|
||||
* Visibility issues
|
||||
* Field name hides field in superclass(*)
|
||||
* Inner class field hides outer class field(*)
|
||||
* Local variable hides member variable(*)
|
||||
* Method overloads method of superclass(*)
|
||||
* Method overrides private method of superclass(*)
|
||||
* Method overrides static method of superclass(*)
|
||||
* Parameter hides member variable(*)
|
||||
52
plugins/InspectionGadgets/InspectionGadgets.iml
Normal file
52
plugins/InspectionGadgets/InspectionGadgets.iml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4" relativePaths="true" type="JAVA_MODULE">
|
||||
<component name="ModuleRootManager" />
|
||||
<component name="NewModuleRootManager">
|
||||
<output url="file://$MODULE_DIR$/classes" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/lib/jdom.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/lib/idea.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/lib/openapi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntryProperties />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
221
plugins/InspectionGadgets/InspectionGadgets.ipr
Normal file
221
plugins/InspectionGadgets/InspectionGadgets.ipr
Normal file
@@ -0,0 +1,221 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4" relativePaths="false">
|
||||
<component name="AntConfiguration">
|
||||
<defaultAnt bundledAnt="true" />
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml">
|
||||
<additionalClassPath>
|
||||
<entry path="file://$APPLICATION_HOME_DIR$/redist/forms_rt.jar" />
|
||||
<entry path="file://$APPLICATION_HOME_DIR$/redist/javac2.jar" />
|
||||
<entry path="file://$APPLICATION_HOME_DIR$/lib/bcel.jar" />
|
||||
<entry path="file://$APPLICATION_HOME_DIR$/lib/jdom.jar" />
|
||||
<entry path="file://$APPLICATION_HOME_DIR$/lib/idea_rt.jar" />
|
||||
</additionalClassPath>
|
||||
<antReference projectDefault="true" />
|
||||
<customJdkName value="java version "1.4.2_05"" />
|
||||
<maximumHeapSize value="128" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
</component>
|
||||
<component name="BattleSpaces" />
|
||||
<component name="CodeStyleSettingsManager">
|
||||
<option name="PER_PROJECT_SETTINGS" />
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="false" />
|
||||
</component>
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<option name="CLEAR_OUTPUT_DIRECTORY" value="false" />
|
||||
<option name="DEPLOY_AFTER_MAKE" value="0" />
|
||||
<excludeFromCompile>
|
||||
<directory url="file://$PROJECT_DIR$/test" includeSubdirectories="true" />
|
||||
</excludeFromCompile>
|
||||
<resourceExtensions>
|
||||
<entry name=".+\.(properties|xml|html|dtd|tld)" />
|
||||
<entry name=".+\.(gif|png|jpeg|jpg)" />
|
||||
</resourceExtensions>
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="?*.properties" />
|
||||
<entry name="?*.xml" />
|
||||
<entry name="?*.gif" />
|
||||
<entry name="?*.png" />
|
||||
<entry name="?*.jpeg" />
|
||||
<entry name="?*.jpg" />
|
||||
<entry name="?*.html" />
|
||||
<entry name="?*.dtd" />
|
||||
<entry name="?*.tld" />
|
||||
</wildcardResourcePatterns>
|
||||
</component>
|
||||
<component name="CycleKillerQQC" />
|
||||
<component name="DataSourceManagerImpl" />
|
||||
<component name="DependencyValidationManager" />
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points />
|
||||
</component>
|
||||
<component name="ExportToHTMLSettings">
|
||||
<option name="PRINT_LINE_NUMBERS" value="false" />
|
||||
<option name="OPEN_IN_BROWSER" value="false" />
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
</component>
|
||||
<component name="GUI Designer component loader factory" />
|
||||
<component name="JavacSettings">
|
||||
<option name="DEBUGGING_INFO" value="true" />
|
||||
<option name="GENERATE_NO_WARNINGS" value="false" />
|
||||
<option name="DEPRECATION" value="true" />
|
||||
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
|
||||
<option name="MAXIMUM_HEAP_SIZE" value="128" />
|
||||
<option name="USE_GENERICS_COMPILER" value="false" />
|
||||
</component>
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
<option name="OPTION_HIERARCHY" value="true" />
|
||||
<option name="OPTION_NAVIGATOR" value="true" />
|
||||
<option name="OPTION_INDEX" value="true" />
|
||||
<option name="OPTION_SEPARATE_INDEX" value="true" />
|
||||
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
|
||||
<option name="OPTION_DEPRECATED_LIST" value="true" />
|
||||
<option name="OTHER_OPTIONS" value="" />
|
||||
<option name="HEAP_SIZE" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
</component>
|
||||
<component name="JikesSettings">
|
||||
<option name="JIKES_PATH" value="" />
|
||||
<option name="DEBUGGING_INFO" value="true" />
|
||||
<option name="DEPRECATION" value="true" />
|
||||
<option name="GENERATE_NO_WARNINGS" value="false" />
|
||||
<option name="IS_EMACS_ERRORS_MODE" value="true" />
|
||||
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
|
||||
</component>
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/InspectionGadgets.iml" filepath="$PROJECT_DIR$/InspectionGadgets.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="java version "1.5.0-beta2"" />
|
||||
<component name="RmicSettings">
|
||||
<option name="IS_EANABLED" value="false" />
|
||||
<option name="DEBUGGING_INFO" value="true" />
|
||||
<option name="GENERATE_NO_WARNINGS" value="false" />
|
||||
<option name="GENERATE_IIOP_STUBS" value="false" />
|
||||
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
|
||||
</component>
|
||||
<component name="com.siyeh.metrics.MetricsReloaded">
|
||||
<option name="selectedProfile" value="Default" />
|
||||
<option name="autoscroll" value="false" />
|
||||
<option name="includeTestClasses" value="false" />
|
||||
<option name="flattenInnerClasses" value="false" />
|
||||
<option name="cycleTableSpecificationString" value="" />
|
||||
</component>
|
||||
<component name="libraryTable" />
|
||||
<component name="uidesigner-configuration">
|
||||
<option name="INSTRUMENT_CLASSES" value="true" />
|
||||
<option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
717
plugins/InspectionGadgets/InspectionGadgets.iws
Normal file
717
plugins/InspectionGadgets/InspectionGadgets.iws
Normal file
@@ -0,0 +1,717 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4" relativePaths="false">
|
||||
<component name="AspectsView" />
|
||||
<component name="BookmarkManager" />
|
||||
<component name="CheckinPanelState" />
|
||||
<component name="Commander">
|
||||
<leftPanel />
|
||||
<rightPanel />
|
||||
<splitter proportion="0.5" />
|
||||
</component>
|
||||
<component name="CompilerWorkspaceConfiguration">
|
||||
<option name="COMPILE_IN_BACKGROUND" value="false" />
|
||||
<option name="AUTO_SHOW_ERRORS_IN_EDITOR" value="true" />
|
||||
<option name="CLOSE_MESSAGE_VIEW_IF_SUCCESS" value="true" />
|
||||
<option name="COMPILE_DEPENDENT_FILES" value="true" />
|
||||
</component>
|
||||
<component name="Cvs2Configuration">
|
||||
<option name="ON_FILE_ADDING" value="0" />
|
||||
<option name="ON_FILE_REMOVING" value="0" />
|
||||
<option name="PRUNE_EMPTY_DIRECTORIES" value="true" />
|
||||
<option name="SHOW_ADD_OPTIONS" value="true" />
|
||||
<option name="SHOW_REMOVE_OPTIONS" value="true" />
|
||||
<option name="MERGING_MODE" value="0" />
|
||||
<option name="MERGE_WITH_BRANCH1_NAME" value="HEAD" />
|
||||
<option name="MERGE_WITH_BRANCH2_NAME" value="HEAD" />
|
||||
<option name="RESET_STICKY" value="false" />
|
||||
<option name="CREATE_NEW_DIRECTORIES" value="true" />
|
||||
<option name="DEFAULT_TEXT_FILE_SUBSTITUTION" value="kv" />
|
||||
<option name="PROCESS_UNKNOWN_FILES" value="false" />
|
||||
<option name="PROCESS_DELETED_FILES" value="false" />
|
||||
<option name="SHOW_EDIT_DIALOG" value="true" />
|
||||
<option name="RESERVED_EDIT" value="false" />
|
||||
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
|
||||
<option name="SHOW_CHECKOUT_OPTIONS" value="true" />
|
||||
<option name="CHECKOUT_DATE_OR_REVISION_SETTINGS">
|
||||
<value>
|
||||
<option name="BRANCH" value="" />
|
||||
<option name="DATE" value="" />
|
||||
<option name="USE_BRANCH" value="false" />
|
||||
<option name="USE_DATE" value="false" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="UPDATE_DATE_OR_REVISION_SETTINGS">
|
||||
<value>
|
||||
<option name="BRANCH" value="" />
|
||||
<option name="DATE" value="" />
|
||||
<option name="USE_BRANCH" value="false" />
|
||||
<option name="USE_DATE" value="false" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="SHOW_CHANGES_REVISION_SETTINGS">
|
||||
<value>
|
||||
<option name="BRANCH" value="PALLADA_RELEASE" />
|
||||
<option name="DATE" value="" />
|
||||
<option name="USE_BRANCH" value="true" />
|
||||
<option name="USE_DATE" value="false" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="SHOW_OUTPUT" value="false" />
|
||||
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
|
||||
<option name="ADD_WATCH_INDEX" value="0" />
|
||||
<option name="REMOVE_WATCH_INDEX" value="0" />
|
||||
<option name="UPDATE_KEYWORD_SUBSTITUTION" value="NONE" />
|
||||
<option name="MAKE_NEW_FILES_READONLY" value="false" />
|
||||
<option name="SHOW_CORRUPTED_PROJECT_FILES" value="0" />
|
||||
<option name="TAG_AFTER_FILE_COMMIT" value="false" />
|
||||
<option name="OVERRIDE_EXISTING_TAG_FOR_FILE" value="true" />
|
||||
<option name="TAG_AFTER_FILE_COMMIT_NAME" value="" />
|
||||
<option name="TAG_AFTER_PROJECT_COMMIT" value="false" />
|
||||
<option name="OVERRIDE_EXISTING_TAG_FOR_PROJECT" value="true" />
|
||||
<option name="TAG_AFTER_PROJECT_COMMIT_NAME" value="" />
|
||||
<option name="CLEAN_COPY" value="false" />
|
||||
</component>
|
||||
<component name="CvsTabbedWindow" />
|
||||
<component name="DaemonCodeAnalyzer">
|
||||
<disable_hints />
|
||||
</component>
|
||||
<component name="DebuggerManager">
|
||||
<line_breakpoints />
|
||||
<exception_breakpoints>
|
||||
<breakpoint_any>
|
||||
<option name="NOTIFY_CAUGHT" value="true" />
|
||||
<option name="NOTIFY_UNCAUGHT" value="true" />
|
||||
<option name="ENABLED" value="false" />
|
||||
<option name="SUSPEND_POLICY" value="SuspendAll" />
|
||||
<option name="LOG_ENABLED" value="false" />
|
||||
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||
<option name="COUNT_FILTER_ENABLED" value="false" />
|
||||
<option name="COUNT_FILTER" value="0" />
|
||||
<option name="CONDITION_ENABLED" value="false" />
|
||||
<option name="CLASS_FILTERS_ENABLED" value="false" />
|
||||
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
|
||||
<option name="myCondition" value="" />
|
||||
<option name="myLogMessage" value="" />
|
||||
</breakpoint_any>
|
||||
</exception_breakpoints>
|
||||
<field_breakpoints />
|
||||
<method_breakpoints />
|
||||
</component>
|
||||
<component name="ErrorTreeViewConfiguration">
|
||||
<option name="IS_AUTOSCROLL_TO_SOURCE" value="true" />
|
||||
<option name="HIDE_WARNINGS" value="false" />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf>
|
||||
<file leaf-file-name="ForCanBeForeachInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/ForCanBeForeachInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="33" selection-start="0" selection-end="33877" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="PointlessArithmeticExpressionInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/PointlessArithmeticExpressionInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="22" column="26" selection-start="779" selection-end="779" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="PointlessBitwiseExpressionInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/PointlessBitwiseExpressionInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="23" column="30" selection-start="0" selection-end="8962" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="PointlessBooleanExpressionInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/PointlessBooleanExpressionInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="45" selection-start="742" selection-end="742" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="ReplaceAssignmentWithOperatorAssignmentInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/ReplaceAssignmentWithOperatorAssignmentInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="16" column="26" selection-start="0" selection-end="4649" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="UnnecessaryBoxingInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/UnnecessaryBoxingInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="23" column="22" selection-start="0" selection-end="4562" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="UnnecessaryParenthesesInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/UnnecessaryParenthesesInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="21" column="42" selection-start="708" selection-end="708" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="UnnecessaryThisInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/UnnecessaryThisInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="21" column="41" selection-start="709" selection-end="709" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="LocalVariableHidingMemberVariableInspection.java" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/visibility/LocalVariableHidingMemberVariableInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="26" column="71" selection-start="812" selection-end="812" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="IncompatibleMaskInspection.java" pinned="false" current="true" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/bugs/IncompatibleMaskInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="57" selection-start="672" selection-end="672" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="HierarchyBrowserManager">
|
||||
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
|
||||
<option name="SORT_ALPHABETICALLY" value="false" />
|
||||
<option name="HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED" value="false" />
|
||||
</component>
|
||||
<component name="InspectionManager">
|
||||
<option name="AUTOSCROLL_TO_SOURCE" value="false" />
|
||||
<option name="SPLITTER_PROPORTION" value="0.49470338" />
|
||||
<profile name="QueryUpdate" />
|
||||
</component>
|
||||
<component name="J2EEProjectPane">
|
||||
<setting name="SHOW_AS_DEPLOYMENT_VIEW" value="false" />
|
||||
</component>
|
||||
<component name="ModuleEditorState">
|
||||
<option name="LAST_EDITED_MODULE_NAME" value="InspectionGadgets" />
|
||||
<option name="LAST_EDITED_TAB_NAME" value="Paths" />
|
||||
</component>
|
||||
<component name="NamedScopeManager" />
|
||||
<component name="PackagesPane">
|
||||
<expanded_node url="" module="InspectionGadgets" type="module" />
|
||||
</component>
|
||||
<component name="ProjectPane">
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/psiutils" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="" module="InspectionGadgets" type="module" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test/com/siyeh/igtest/performance" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/imports" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/portability" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test/com/siyeh/igtest/bugs" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/junit" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/naming" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/performance" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/serialization" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/visibility" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/threading" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/confusing" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/META-INF" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test/com/siyeh/igtest" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/inspectionDescriptions" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test/com/siyeh/igtest/junit" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/abstraction" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/bugs" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src/com/siyeh/ig/classlayout" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test/com/siyeh/igtest/threading" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/src" module="InspectionGadgets" type="directory" />
|
||||
<expanded_node url="file://$PROJECT_DIR$/test/com/siyeh/igtest/serialization" module="InspectionGadgets" type="directory" />
|
||||
</component>
|
||||
<component name="ProjectReloadState">
|
||||
<option name="STATE" value="0" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" splitterProportion="0.5">
|
||||
<flattenPackages ProjectPane="false" />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
<showLibraryContents />
|
||||
<hideEmptyPackages />
|
||||
<abbreviatePackageNames />
|
||||
<showStructure PackagesPane="false" ProjectPane="false" />
|
||||
<autoscrollToSource ProjectPane="true" />
|
||||
<autoscrollFromSource ProjectPane="true" />
|
||||
</navigator>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="vcs_file_view_treeWidth2" value="47" />
|
||||
<property name="GoToClass.includeJavaFiles" value="false" />
|
||||
<property name="vcs_file_view_flatOrder1" value="1" />
|
||||
<property name="MemberChooser.copyJavadoc" value="false" />
|
||||
<property name="vcs_file_view_treeOrder4" value="4" />
|
||||
<property name="GoToFile.includeJavaFiles" value="false" />
|
||||
<property name="vcs_file_view_flatWidth2" value="53" />
|
||||
<property name="vcs_file_view_flatWidth5" value="52" />
|
||||
<property name="GoToClass.includeLibraries" value="false" />
|
||||
<property name="vcs_file_view_flatOrder3" value="3" />
|
||||
<property name="MemberChooser.showClasses" value="true" />
|
||||
<property name="vcs_file_view_treeWidth0" value="310" />
|
||||
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
|
||||
<property name="vcs_file_view_treeOrder0" value="0" />
|
||||
<property name="vcs_file_view_flatOrder4" value="4" />
|
||||
<property name="MemberChooser.sorted" value="false" />
|
||||
<property name="vcs_file_view_flatOrder5" value="5" />
|
||||
<property name="vcs_file_view_treeOrder3" value="3" />
|
||||
<property name="vcs_file_view_flatWidth4" value="53" />
|
||||
<property name="vcs_file_view_treeWidth1" value="48" />
|
||||
<property name="vcs_file_view_flatOrder2" value="2" />
|
||||
<property name="vcs_file_view_treeWidth4" value="49" />
|
||||
<property name="vcs_file_view_treeOrder2" value="2" />
|
||||
<property name="vcs_file_view_flatWidth3" value="54" />
|
||||
<property name="vcs_file_view_treeWidth3" value="50" />
|
||||
<property name="vcs_file_view_flatOrder0" value="0" />
|
||||
<property name="vcs_file_view_flatWidth0" value="236" />
|
||||
<property name="vcs_file_view_treeOrder1" value="1" />
|
||||
<property name="vcs_file_view_flatWidth1" value="56" />
|
||||
</component>
|
||||
<component name="PsiViewer.ProjectComponent">
|
||||
<option name="HIGHLIGHT" value="false" />
|
||||
<option name="FILTER_WHITESPACE" value="false" />
|
||||
<option name="SHOW_PROPERTIES" value="true" />
|
||||
<option name="SPLIT_DIVIDER_POSITION" value="290" />
|
||||
<option name="AUTOSCROLL_TO_SOURCE" value="false" />
|
||||
<option name="AUTOSCROLL_FROM_SOURCE" value="false" />
|
||||
</component>
|
||||
<component name="RestoreUpdateTree" />
|
||||
<component name="RunManager">
|
||||
<activeType name="Application" />
|
||||
<configuration selected="false" default="true" type="#com.intellij.j2ee.web.jsr45.JSR45ConfigurationFactory" factoryName="Remote">
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="7001" />
|
||||
<option name="LOCAL" value="false" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OPEN_IN_BROWSER_URL" value="/" />
|
||||
<option name="COMMON_VM_ARGUMENTS" value="" />
|
||||
<option name="JSP_PACKAGE" value="" />
|
||||
<option name="VM_OPTS" value="VM_OPTS" />
|
||||
<option name="LOCAL_PORT" value="80" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="WebLogic Instance" factoryName="Remote">
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="7001" />
|
||||
<option name="LOCAL" value="false" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OPEN_IN_BROWSER_URL" value="/" />
|
||||
<option name="COMMON_VM_ARGUMENTS" value="" />
|
||||
<option name="DOMAIN_PATH" value="" />
|
||||
<option name="USER" value="weblogic" />
|
||||
<option name="PASSWORD" value="weblogic" />
|
||||
<option name="SERVER_NAME" value="myserver" />
|
||||
<option name="DOMAIN_NAME" value="mydomain" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="#com.intellij.j2ee.web.tomcat.TomcatRunConfigurationFactory" factoryName="Local">
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="7001" />
|
||||
<option name="LOCAL" value="true" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OPEN_IN_BROWSER_URL" value="/" />
|
||||
<option name="COMMON_VM_ARGUMENTS" value="" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="JUnit" factoryName="JUnit">
|
||||
<module name="" />
|
||||
<option name="PACKAGE_NAME" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="METHOD_NAME" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="ADDITIONAL_CLASS_PATH" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="wholeProject" />
|
||||
</option>
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="#com.intellij.j2ee.web.jsr45.JSR45ConfigurationFactory" factoryName="Local">
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="7001" />
|
||||
<option name="LOCAL" value="true" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OPEN_IN_BROWSER_URL" value="/" />
|
||||
<option name="COMMON_VM_ARGUMENTS" value="" />
|
||||
<option name="JSP_PACKAGE" value="" />
|
||||
<option name="VM_OPTS" value="VM_OPTS" />
|
||||
<option name="LOCAL_PORT" value="80" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="WebLogic Instance" factoryName="Local">
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="7001" />
|
||||
<option name="LOCAL" value="true" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OPEN_IN_BROWSER_URL" value="/" />
|
||||
<option name="COMMON_VM_ARGUMENTS" value="" />
|
||||
<option name="DOMAIN_PATH" value="" />
|
||||
<option name="USER" value="weblogic" />
|
||||
<option name="PASSWORD" value="weblogic" />
|
||||
<option name="SERVER_NAME" value="myserver" />
|
||||
<option name="DOMAIN_NAME" value="mydomain" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="Applet" factoryName="Applet">
|
||||
<module name="" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="HTML_FILE_NAME" />
|
||||
<option name="HTML_USED" value="false" />
|
||||
<option name="WIDTH" value="400" />
|
||||
<option name="HEIGHT" value="300" />
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="Remote" factoryName="Remote">
|
||||
<option name="USE_SOCKET_TRANSPORT" value="true" />
|
||||
<option name="SERVER_MODE" value="false" />
|
||||
<option name="SHMEM_ADDRESS" value="javadebug" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="5005" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="#com.intellij.j2ee.web.tomcat.TomcatRunConfigurationFactory" factoryName="Remote">
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="7001" />
|
||||
<option name="LOCAL" value="false" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OPEN_IN_BROWSER_URL" value="/" />
|
||||
<option name="COMMON_VM_ARGUMENTS" value="" />
|
||||
</configuration>
|
||||
<configuration selected="false" default="true" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="PROGRAM_PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<module name="" />
|
||||
</configuration>
|
||||
<configuration selected="true" default="false" name="InspectionList" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="com.siyeh.ig.InspectionGadgetsPlugin" />
|
||||
<option name="VM_PARAMETERS" value="" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<module name="InspectionGadgets" />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="1039" />
|
||||
<option name="TRANSPORT" value="0" />
|
||||
<option name="LOCAL" value="false" />
|
||||
</RunnerSettings>
|
||||
<RunnerSettings RunnerId="Run" />
|
||||
<ConfigurationWrapper RunnerId="Debug" />
|
||||
<ConfigurationWrapper RunnerId="Run" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SQL">
|
||||
<export>
|
||||
<html table="border: 1px solid black; border-spacing:0px" cell="border: 1px solid black" header="background: darkgrey; font-weight:bold; text-align: center" row1="background: white" row2="background: lightgrey" alternate="true" interval="1" />
|
||||
<csvExport delimiter="," text=""" />
|
||||
</export>
|
||||
<general />
|
||||
<databases savePasswords="false" encodePasswords="true" />
|
||||
<queries projectClassLoader="false" save="false" />
|
||||
<results primaryKeyCols="true" saveTableConfig="false">
|
||||
<rowLimit enabled="true" value="1000" />
|
||||
<resizeColumns toHeader="true" toContent="true" />
|
||||
</results>
|
||||
</component>
|
||||
<component name="SelectInManager">
|
||||
<target name="Project" />
|
||||
<target name="File Structure" />
|
||||
<target name="J2EE View" />
|
||||
<target name="Packages" />
|
||||
<target name="Commander" />
|
||||
</component>
|
||||
<component name="StarteamConfiguration">
|
||||
<option name="SERVER" value="" />
|
||||
<option name="PORT" value="49201" />
|
||||
<option name="USER" value="" />
|
||||
<option name="PASSWORD" value="" />
|
||||
<option name="PROJECT" value="" />
|
||||
<option name="VIEW" value="" />
|
||||
<option name="ALTERNATIVE_WORKING_PATH" value="" />
|
||||
</component>
|
||||
<component name="StructuralSearchPlugin" />
|
||||
<component name="StructureViewFactory">
|
||||
<option name="SORT_MODE" value="0" />
|
||||
<option name="GROUP_INHERITED" value="true" />
|
||||
<option name="AUTOSCROLL_MODE" value="true" />
|
||||
<option name="SHOW_FIELDS" value="true" />
|
||||
<option name="AUTOSCROLL_FROM_SOURCE" value="false" />
|
||||
<option name="GROUP_GETTERS_AND_SETTERS" value="true" />
|
||||
<option name="SHOW_INHERITED" value="false" />
|
||||
<option name="HIDE_NOT_PUBLIC" value="false" />
|
||||
</component>
|
||||
<component name="TodoView" selected-index="0">
|
||||
<todo-panel id="selected-file">
|
||||
<are-packages-shown value="false" />
|
||||
<flatten-packages value="false" />
|
||||
<is-autoscroll-to-source value="true" />
|
||||
</todo-panel>
|
||||
<todo-panel id="all">
|
||||
<are-packages-shown value="true" />
|
||||
<flatten-packages value="false" />
|
||||
<is-autoscroll-to-source value="true" />
|
||||
</todo-panel>
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="-4" y="-4" width="1032" height="748" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="SQL" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="PsiViewer" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.36172345" order="3" />
|
||||
<window_info id="CVS" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.42989215" order="0" />
|
||||
<window_info id="Code Outline" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="3" />
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="10" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="docked" type="docked" visible="true" weight="0.2626953" order="0" />
|
||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33281973" order="4" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.249742" order="1" />
|
||||
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.30046225" order="1" />
|
||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.3990755" order="9" />
|
||||
<window_info id="Dependency Cycles" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="2" />
|
||||
<window_info id="Metrics" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="1" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.48826292" order="5" />
|
||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="2" />
|
||||
<window_info id="File View" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.50097656" order="3" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="sliding" type="sliding" visible="false" weight="0.4" order="0" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.4" order="7" />
|
||||
<window_info id="Workspaces" active="false" anchor="left" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="3" />
|
||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="3" />
|
||||
<window_info id="CycleKillerQQC" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="CVS File View" active="false" anchor="right" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="3" />
|
||||
<window_info id="BattleSpaces" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="Metrics Reloaded" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="Clash" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.33" order="11" />
|
||||
<window_info id="Web" active="false" anchor="left" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="2" />
|
||||
<window_info id="EJB" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="6" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.25" order="8" />
|
||||
<window_info id="Update File" active="false" anchor="bottom" auto_hide="false" internal_type="docked" type="docked" visible="false" weight="0.32973805" order="11" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="VCS.FileViewConfiguration">
|
||||
<option name="SELECTED_STATUSES" value="Unknown" />
|
||||
<option name="SELECTED_COLUMNS" value="DEFAULT" />
|
||||
<option name="SHOW_FILTERS" value="true" />
|
||||
<option name="CUSTOMIZE_VIEW" value="true" />
|
||||
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="PUT_FOCUS_INTO_COMMENT" value="false" />
|
||||
<option name="SHOW_CHECKIN_OPTIONS" value="true" />
|
||||
<option name="FORCE_NON_EMPTY_COMMENT" value="false" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="" />
|
||||
<option name="SAVE_LAST_COMMIT_MESSAGE" value="true" />
|
||||
<option name="CHECKIN_DIALOG_SPLITTER_PROPORTION" value="0.8" />
|
||||
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||
<option name="OPTIMIZE_IMPORTS_BEFORE_FILE_COMMIT" value="false" />
|
||||
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
|
||||
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
|
||||
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
|
||||
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
|
||||
<option name="ACTIVE_VCS_NAME" value="CVS" />
|
||||
<option name="UPDATE_GROUP_BY_PACKAGES" value="true" />
|
||||
<option name="SHOW_UPDATE_OPTIONS" value="false" />
|
||||
</component>
|
||||
<component name="VssConfiguration">
|
||||
<option name="CLIENT_PATH" value="" />
|
||||
<option name="SRCSAFEINI_PATH" value="" />
|
||||
<option name="USER_NAME" value="" />
|
||||
<option name="PWD" value="" />
|
||||
<option name="SHOW_CHECKOUT_OPTIONS" value="true" />
|
||||
<option name="SHOW_ADD_OPTIONS" value="true" />
|
||||
<option name="VSS_IS_INITIALIZED" value="true" />
|
||||
<option name="SHOW_UNDOCHECKOUT_OPTIONS" value="true" />
|
||||
<option name="SHOW_DIFF_OPTIONS" value="true" />
|
||||
<option name="SHOW_GET_OPTIONS" value="true" />
|
||||
<option name="REUSE_LAST_COMMENT" value="false" />
|
||||
<CheckoutOptions>
|
||||
<option name="COMMENT" value="" />
|
||||
<option name="DO_NOT_GET_LATEST_VERSION" value="false" />
|
||||
<option name="REPLACE_WRITABLE" value="false" />
|
||||
<option name="RECURSIVE" value="false" />
|
||||
</CheckoutOptions>
|
||||
<CheckinOptions>
|
||||
<option name="COMMENT" value="" />
|
||||
<option name="KEEP_CHECKED_OUT" value="false" />
|
||||
<option name="RECURSIVE" value="false" />
|
||||
</CheckinOptions>
|
||||
<AddOptions>
|
||||
<option name="COMMENT" value="" />
|
||||
<option name="STORE_ONLY_LATEST_VERSION" value="false" />
|
||||
<option name="CHECK_OUT_IMMEDIATELY" value="false" />
|
||||
<option name="FILE_TYPE" value="0" />
|
||||
</AddOptions>
|
||||
<UndocheckoutOptions>
|
||||
<option name="MAKE_WRITABLE" value="false" />
|
||||
<option name="REPLACE_LOCAL_COPY" value="0" />
|
||||
<option name="RECURSIVE" value="false" />
|
||||
</UndocheckoutOptions>
|
||||
<GetOptions>
|
||||
<option name="REPLACE_WRITABLE" value="0" />
|
||||
<option name="MAKE_WRITABLE" value="false" />
|
||||
<option name="RECURSIVE" value="false" />
|
||||
</GetOptions>
|
||||
</component>
|
||||
<component name="WorkspaceManager">
|
||||
<option name="workspaces">
|
||||
<value>
|
||||
<list size="0" />
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="antWorkspaceConfiguration">
|
||||
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
|
||||
<option name="FILTER_TARGETS" value="false" />
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml">
|
||||
<antCommandLine value="" />
|
||||
<runInBackground value="true" />
|
||||
<targetFilters>
|
||||
<filter targetName="compile" isVisible="true" />
|
||||
<filter targetName="init" isVisible="false" />
|
||||
<filter targetName="clean" isVisible="true" />
|
||||
<filter targetName="prepare" isVisible="false" />
|
||||
<filter targetName="deploy" isVisible="true" />
|
||||
<filter targetName="sync" isVisible="true" />
|
||||
<filter targetName="ship" isVisible="true" />
|
||||
</targetFilters>
|
||||
<treeView value="true" />
|
||||
<verbose value="false" />
|
||||
<viewClosedWhenNoErrors value="false" />
|
||||
</buildFile>
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/psiutils/ExpressionEquivalenceChecker.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="9" column="27" selection-start="0" selection-end="15020" vertical-scroll-proportion="0.478125">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/psiutils/ImportUtils.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="5" column="53" selection-start="0" selection-end="6821" vertical-scroll-proportion="0.265625">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/psiutils/InitializationReadUtils.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="23" column="27" selection-start="0" selection-end="20990" vertical-scroll-proportion="0.796875">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/psiutils/ParenthesesUtils.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="14" column="13" selection-start="255" selection-end="255" vertical-scroll-proportion="0.53125">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/psiutils/RecursionUtils.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="16" column="42" selection-start="0" selection-end="25649" vertical-scroll-proportion="0.8528428">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/ForCanBeForeachInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="33" selection-start="0" selection-end="33877" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/PointlessArithmeticExpressionInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="22" column="26" selection-start="779" selection-end="779" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/PointlessBitwiseExpressionInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="23" column="30" selection-start="0" selection-end="8962" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/PointlessBooleanExpressionInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="45" selection-start="742" selection-end="742" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/ReplaceAssignmentWithOperatorAssignmentInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="16" column="26" selection-start="0" selection-end="4649" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/UnnecessaryBoxingInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="23" column="22" selection-start="0" selection-end="4562" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/UnnecessaryParenthesesInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="21" column="42" selection-start="708" selection-end="708" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/verbose/UnnecessaryThisInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="21" column="41" selection-start="709" selection-end="709" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/visibility/LocalVariableHidingMemberVariableInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="26" column="71" selection-start="812" selection-end="812" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/com/siyeh/ig/bugs/IncompatibleMaskInspection.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="20" column="57" selection-start="672" selection-end="672" vertical-scroll-proportion="0.03256705">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
20
plugins/InspectionGadgets/InspectionGadgetsPlugin.iml
Normal file
20
plugins/InspectionGadgets/InspectionGadgetsPlugin.iml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4" relativePaths="true" type="JAVA_MODULE">
|
||||
<component name="ModuleRootManager" />
|
||||
<component name="NewModuleRootManager">
|
||||
<output url="file://$MODULE_DIR$/classes" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="JDOM" level="project" />
|
||||
<orderEntry type="library" name="JUnit" level="project" />
|
||||
<orderEntry type="library" name="Log4J" level="project" />
|
||||
<orderEntry type="module" module-name="openapi" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntryProperties />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
26
plugins/InspectionGadgets/META-INF/plugin.xml
Normal file
26
plugins/InspectionGadgets/META-INF/plugin.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<idea-plugin>
|
||||
<name>Inspection Gadgets</name>
|
||||
<category>inspection</category>
|
||||
<description>Over 320 new automated code inspections for IDEA</description>
|
||||
<vendor>InspectionGadgets Software</vendor>
|
||||
<version>1.0</version>
|
||||
<idea-version min="4.0" max="4.1"/>
|
||||
|
||||
<application-components>
|
||||
<component>
|
||||
<implementation-class>com.siyeh.ig.InspectionGadgetsPlugin</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
|
||||
<actions>
|
||||
|
||||
<group>
|
||||
<action id="InspectionGadgets.Toggle"
|
||||
class="com.siyeh.ig.TogglePluginAction"
|
||||
text="_InspectionGadgets error highlighting">
|
||||
<keyboard-shortcut first-keystroke="alt I" keymap="$default"/>
|
||||
</action>
|
||||
<add-to-group group-id="AnalyzeMenu" anchor="last"/>
|
||||
</group>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
76
plugins/InspectionGadgets/build.xml
Normal file
76
plugins/InspectionGadgets/build.xml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<project name="InspectionGadgets" default="compile">
|
||||
<taskdef name="javac2" classname="com.intellij.uiDesigner.ant.Javac2" classpathref="project.class.path"/>
|
||||
<property name="src.dir" value="src"/>
|
||||
<property name="idea.dir" value="c:/IntelliJ-IDEA-3075"/>
|
||||
<property name="idea.plugin.dir" value="${idea.dir}/plugins"/>
|
||||
<property name="debug" value="true"/>
|
||||
<property name="optimize" value="off"/>
|
||||
<property name="deprecation" value="off"/>
|
||||
<property name="project.fullname" value="InspectionGadgets"/>
|
||||
<property name="project.version" value="1.0"/>
|
||||
<property name="jar.file" value="InspectionGadgets.jar"/>
|
||||
<property name="dist.zip.file" value="${project.fullname}.${project.version}.zip"/>
|
||||
|
||||
<path id="project.class.path">
|
||||
<pathelement location="${idea.dir}/lib/openAPI.jar"/>
|
||||
<pathelement location="${idea.dir}/lib/idea.jar"/>
|
||||
<pathelement location="${idea.dir}/lib/jdom.jar"/>
|
||||
</path>
|
||||
|
||||
<target name="init">
|
||||
<property name="build.classes.dir" value="classes"/>
|
||||
<property name="src.dir" value="src"/>
|
||||
<property name="build.compiler" value="modern"/>
|
||||
</target>
|
||||
|
||||
<target name="prepare" depends="init">
|
||||
<mkdir dir="${build.classes.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="prepare">
|
||||
<javac2 srcdir="${src.dir}" destdir="${build.classes.dir}" includes="com/siyeh/**" debug="${debug}">
|
||||
<classpath refid="project.class.path"/>
|
||||
</javac2>
|
||||
</target>
|
||||
|
||||
<target name="deploy" depends="clean, compile" description="deploy the plugin">
|
||||
<delete file="${jar.file}"/>
|
||||
<jar
|
||||
jarfile="${jar.file}">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<fileset dir=".">
|
||||
<include name="META-INF/plugin.xml"/>
|
||||
</fileset>
|
||||
<fileset dir="src">
|
||||
<include name="inspectionDescriptions/*.html"/>
|
||||
</fileset>
|
||||
</jar>
|
||||
<mkdir dir="${idea.plugin.dir}"/>
|
||||
<copy file="${jar.file}" todir="${idea.plugin.dir}" overwrite="true" />
|
||||
</target>
|
||||
|
||||
<target name="clean" depends="init" description="Cleans up the distribution">
|
||||
<delete failonerror="false" dir="${build.classes.dir}"/>
|
||||
<delete failonerror="false" file="${jar.file}"/>
|
||||
</target>
|
||||
|
||||
<target name="ship" depends="init" description="Makes jars for shipping">
|
||||
<move file="${jar.file}" todir="C:\" />
|
||||
<delete dir="${build.classes.dir}"/>
|
||||
<zip zipfile="c:\${project.fullname}.zip">
|
||||
<fileset dir=".">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="sync" depends="clean" description="Dump it to the watch">
|
||||
<sync todir="E:\InspectionGadgets">
|
||||
<fileset dir=".">
|
||||
<include name="**/*"/>
|
||||
</fileset>
|
||||
</sync>
|
||||
</target>
|
||||
</project>
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public abstract class BaseInspection extends LocalInspectionTool {
|
||||
private final String m_shortName = null;
|
||||
|
||||
public String getShortName() {
|
||||
if (m_shortName == null) {
|
||||
final Class aClass = getClass();
|
||||
final String name = aClass.getName();
|
||||
return name.substring(name.lastIndexOf((int) '.') + 1, name.length() - "Inspection".length());
|
||||
}
|
||||
return m_shortName;
|
||||
}
|
||||
|
||||
protected abstract BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly);
|
||||
|
||||
protected String buildErrorString(PsiElement location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String buildErrorString(Object arg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForBatchErrors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasQuickFix() {
|
||||
final Method[] methods = getClass().getDeclaredMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
final Method method = methods[i];
|
||||
final String methodName = method.getName();
|
||||
if ("buildFix".equals(methodName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.psi.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseInspectionVisitor extends PsiRecursiveElementVisitor {
|
||||
private final BaseInspection m_inspection;
|
||||
private final InspectionManager m_inspectionManager;
|
||||
private final boolean m_onTheFly;
|
||||
private List m_errors = null;
|
||||
|
||||
protected BaseInspectionVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean onTheFly) {
|
||||
super();
|
||||
m_inspection = inspection;
|
||||
m_inspectionManager = inspectionManager;
|
||||
m_onTheFly = onTheFly;
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
final PsiExpression qualifier = expression.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
qualifier.accept(this);
|
||||
}
|
||||
final PsiReferenceParameterList typeParameters = expression.getParameterList();
|
||||
if (typeParameters != null) {
|
||||
typeParameters.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerMethodCallError(PsiMethodCallExpression expression) {
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final PsiElement nameToken = methodExpression.getReferenceNameElement();
|
||||
registerError(nameToken);
|
||||
}
|
||||
|
||||
protected void registerStatementError(PsiStatement statement) {
|
||||
final PsiElement statementToken = statement.getFirstChild();
|
||||
registerError(statementToken);
|
||||
}
|
||||
|
||||
protected void registerClassError(PsiClass aClass) {
|
||||
final PsiElement nameIdentifier = aClass.getNameIdentifier();
|
||||
registerError(nameIdentifier);
|
||||
}
|
||||
|
||||
protected void registerMethodError(PsiMethod method) {
|
||||
final PsiElement nameIdentifier = method.getNameIdentifier();
|
||||
registerError(nameIdentifier);
|
||||
}
|
||||
|
||||
protected void registerVariableError(PsiVariable variable) {
|
||||
final PsiElement nameIdentifier = variable.getNameIdentifier();
|
||||
registerError(nameIdentifier);
|
||||
}
|
||||
|
||||
protected void registerTypeParameterError(PsiTypeParameter param) {
|
||||
final PsiElement nameIdentifier = param.getNameIdentifier();
|
||||
registerError(nameIdentifier);
|
||||
}
|
||||
|
||||
protected void registerFieldError(PsiField field) {
|
||||
final PsiElement nameIdentifier = field.getNameIdentifier();
|
||||
registerError(nameIdentifier);
|
||||
}
|
||||
|
||||
protected void registerModifierError(String modifier, PsiModifierListOwner parameter) {
|
||||
final PsiModifierList modifiers = parameter.getModifierList();
|
||||
if (modifiers == null) {
|
||||
return;
|
||||
}
|
||||
final PsiElement[] children = modifiers.getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
final PsiElement child = children[i];
|
||||
final String text = child.getText();
|
||||
if (modifier.equals(text)) {
|
||||
registerError(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerError(PsiElement location) {
|
||||
if (location == null) {
|
||||
return;
|
||||
}
|
||||
final LocalQuickFix fix;
|
||||
if (!m_onTheFly && m_inspection.buildQuickFixesOnlyForOnTheFlyErrors()) {
|
||||
fix = null;
|
||||
} else if (m_onTheFly && m_inspection.buildQuickFixesOnlyForBatchErrors()) {
|
||||
fix = null;
|
||||
} else {
|
||||
fix = m_inspection.buildFix(location);
|
||||
}
|
||||
final String description = m_inspection.buildErrorString(location);
|
||||
final ProblemDescriptor problem
|
||||
= m_inspectionManager.createProblemDescriptor(location, description, fix,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
addError(problem);
|
||||
}
|
||||
|
||||
private void addError(ProblemDescriptor problem) {
|
||||
if (m_errors == null) {
|
||||
m_errors = new ArrayList(5);
|
||||
}
|
||||
m_errors.add(problem);
|
||||
}
|
||||
|
||||
protected void registerError(PsiElement location, Object arg) {
|
||||
final LocalQuickFix fix;
|
||||
if (!m_onTheFly && m_inspection.buildQuickFixesOnlyForOnTheFlyErrors()) {
|
||||
fix = null;
|
||||
} else if (m_onTheFly && m_inspection.buildQuickFixesOnlyForBatchErrors()) {
|
||||
fix = null;
|
||||
} else {
|
||||
fix = m_inspection.buildFix(location);
|
||||
}
|
||||
final String description = m_inspection.buildErrorString(arg);
|
||||
final ProblemDescriptor problem
|
||||
= m_inspectionManager.createProblemDescriptor(location, description, fix,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
addError(problem);
|
||||
}
|
||||
|
||||
|
||||
public ProblemDescriptor[] getErrors() {
|
||||
final List errors = m_errors;
|
||||
if (errors == null) {
|
||||
return null;
|
||||
} else {
|
||||
final int numErrors = errors.size();
|
||||
return (ProblemDescriptor[]) errors.toArray(new ProblemDescriptor[numErrors]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
class InspectionComparator implements Comparator {
|
||||
InspectionComparator() {
|
||||
super();
|
||||
}
|
||||
|
||||
public int compare(Object o1, Object o2) {
|
||||
final Class class1 = (Class) o1;
|
||||
final Class class2 = (Class) o2;
|
||||
final LocalInspectionTool inspection1;
|
||||
final LocalInspectionTool inspection2;
|
||||
try {
|
||||
inspection1 = (LocalInspectionTool) class1.newInstance();
|
||||
inspection2 = (LocalInspectionTool) class2.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
return -1;
|
||||
} catch (IllegalAccessException e) {
|
||||
return -1;
|
||||
}
|
||||
final String groupName1 = inspection1.getGroupDisplayName();
|
||||
final String groupName2 = inspection2.getGroupDisplayName();
|
||||
final int groupNameComparison = groupName1.compareTo(groupName2);
|
||||
if (groupNameComparison != 0) {
|
||||
return groupNameComparison;
|
||||
}
|
||||
String displayName1 = inspection1.getDisplayName();
|
||||
String displayName2 = inspection2.getDisplayName();
|
||||
displayName1 = displayName1.toUpperCase();
|
||||
displayName2 = displayName2.toUpperCase();
|
||||
displayName1 = stripLeadingNonCharacters(displayName1);
|
||||
displayName2 = stripLeadingNonCharacters(displayName2);
|
||||
return displayName1.compareTo(displayName2);
|
||||
}
|
||||
|
||||
private static String stripLeadingNonCharacters(String str) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
final char ch = str.charAt(i);
|
||||
if (Character.isLetter(ch)) {
|
||||
return str.substring(i);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
public abstract class InspectionGadgetsFix implements LocalQuickFix {
|
||||
protected void deleteElement(PsiElement element) {
|
||||
try {
|
||||
element.delete();
|
||||
} catch (IncorrectOperationException e) {
|
||||
final Class aClass = getClass();
|
||||
final String className = aClass.getName();
|
||||
final Logger logger = Logger.getInstance(className);
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void replaceExpression(Project project, PsiExpression expression, String newExpression) {
|
||||
try {
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
final PsiElementFactory factory = psiManager.getElementFactory();
|
||||
final PsiExpression newExp = factory.createExpressionFromText(newExpression, null);
|
||||
final PsiElement replacementExp = expression.replace(newExp);
|
||||
final CodeStyleManager styleManager = psiManager.getCodeStyleManager();
|
||||
styleManager.reformat(replacementExp);
|
||||
} catch (IncorrectOperationException e) {
|
||||
final Class aClass = getClass();
|
||||
final String className = aClass.getName();
|
||||
final Logger logger = Logger.getInstance(className);
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void replaceStatement(Project project, PsiStatement statement, String newStatement) {
|
||||
try {
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
final PsiElementFactory factory = psiManager.getElementFactory();
|
||||
final PsiStatement newExp = factory.createStatementFromText(newStatement, null);
|
||||
final PsiElement replacementExp = statement.replace(newExp);
|
||||
final CodeStyleManager styleManager = psiManager.getCodeStyleManager();
|
||||
styleManager.reformat(replacementExp);
|
||||
} catch (IncorrectOperationException e) {
|
||||
final Class aClass = getClass();
|
||||
final String className = aClass.getName();
|
||||
final Logger logger = Logger.getInstance(className);
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.codeInspection.InspectionToolProvider;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.siyeh.ig.abstraction.*;
|
||||
import com.siyeh.ig.bugs.*;
|
||||
import com.siyeh.ig.classlayout.*;
|
||||
import com.siyeh.ig.classmetrics.*;
|
||||
import com.siyeh.ig.cloneable.CloneCallsConstructorsInspection;
|
||||
import com.siyeh.ig.cloneable.CloneCallsSuperCloneInspection;
|
||||
import com.siyeh.ig.cloneable.CloneDeclaresCloneNotSupportedInspection;
|
||||
import com.siyeh.ig.cloneable.CloneableImplementsCloneInspection;
|
||||
import com.siyeh.ig.confusing.*;
|
||||
import com.siyeh.ig.encapsulation.*;
|
||||
import com.siyeh.ig.errorhandling.*;
|
||||
import com.siyeh.ig.finalization.FinalizeCallsSuperFinalizeInspection;
|
||||
import com.siyeh.ig.finalization.FinalizeInspection;
|
||||
import com.siyeh.ig.finalization.FinalizeNotProtectedInspection;
|
||||
import com.siyeh.ig.finalization.NoExplicitFinalizeCallsInspection;
|
||||
import com.siyeh.ig.imports.*;
|
||||
import com.siyeh.ig.initialization.*;
|
||||
import com.siyeh.ig.internationalization.*;
|
||||
import com.siyeh.ig.junit.*;
|
||||
import com.siyeh.ig.logging.ClassWithoutLoggerInspection;
|
||||
import com.siyeh.ig.logging.ClassWithMultipleLoggersInspection;
|
||||
import com.siyeh.ig.logging.NonStaticFinalLoggerInspection;
|
||||
import com.siyeh.ig.maturity.*;
|
||||
import com.siyeh.ig.methodmetrics.*;
|
||||
import com.siyeh.ig.naming.*;
|
||||
import com.siyeh.ig.performance.*;
|
||||
import com.siyeh.ig.portability.*;
|
||||
import com.siyeh.ig.security.CloneableClassInSecureContextInspection;
|
||||
import com.siyeh.ig.security.DeserializableClassInSecureContextInspection;
|
||||
import com.siyeh.ig.security.NonStaticInnerClassInSecureContextInspection;
|
||||
import com.siyeh.ig.security.SerializableClassInSecureContextInspection;
|
||||
import com.siyeh.ig.serialization.*;
|
||||
import com.siyeh.ig.style.*;
|
||||
import com.siyeh.ig.threading.*;
|
||||
import com.siyeh.ig.verbose.*;
|
||||
import com.siyeh.ig.visibility.*;
|
||||
import org.jdom.Element;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class InspectionGadgetsPlugin implements ApplicationComponent,
|
||||
InspectionToolProvider, JDOMExternalizable {
|
||||
private static final int NUM_INSPECTIONS = 360;
|
||||
private final List m_inspectionClasses = new ArrayList(NUM_INSPECTIONS);
|
||||
|
||||
private final InspectionGadgetsConfig m_config = new InspectionGadgetsConfig();
|
||||
|
||||
public static void main(String[] args) {
|
||||
final InspectionGadgetsPlugin plugin = new InspectionGadgetsPlugin();
|
||||
final PrintStream out;
|
||||
if (args.length == 0) {
|
||||
out = System.out;
|
||||
} else {
|
||||
final OutputStream stream;
|
||||
try {
|
||||
stream = new FileOutputStream(args[0]);
|
||||
} catch (final FileNotFoundException e) {
|
||||
return;
|
||||
}
|
||||
out = new PrintStream(stream);
|
||||
}
|
||||
plugin.createDocumentation(out);
|
||||
}
|
||||
|
||||
private void createDocumentation(PrintStream out) {
|
||||
initComponent();
|
||||
final Class[] classes = getInspectionClasses();
|
||||
String currentGroupName = "";
|
||||
|
||||
final int numQuickFixes = countQuickFixes(classes, out);
|
||||
out.println(classes.length + " Inspections");
|
||||
out.println(numQuickFixes + " Quick Fixes");
|
||||
|
||||
for (int i = 0; i < classes.length; i++) {
|
||||
final Class aClass = classes[i];
|
||||
final String className = aClass.getName();
|
||||
try {
|
||||
final LocalInspectionTool inspection = (LocalInspectionTool) aClass.newInstance();
|
||||
final String groupDisplayName = inspection.getGroupDisplayName();
|
||||
if (!groupDisplayName.equals(currentGroupName)) {
|
||||
currentGroupName = groupDisplayName;
|
||||
out.println();
|
||||
out.print(" * ");
|
||||
out.println(currentGroupName);
|
||||
}
|
||||
printInspectionDescription(inspection, out);
|
||||
|
||||
} catch (InstantiationException e) {
|
||||
out.print("Couldn't instantiate ");
|
||||
out.println(className);
|
||||
} catch (IllegalAccessException e) {
|
||||
out.print("Couldn't access ");
|
||||
out.println(className);
|
||||
} catch (ClassCastException e) {
|
||||
out.print("Couldn't cast ");
|
||||
out.println(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void printInspectionDescription(LocalInspectionTool inspection, PrintStream out) {
|
||||
final boolean hasQuickFix = ((BaseInspection) inspection).hasQuickFix();
|
||||
|
||||
final String displayName = inspection.getDisplayName();
|
||||
if (hasQuickFix) {
|
||||
out.print(" * ");
|
||||
out.print(displayName);
|
||||
out.println("(*)");
|
||||
} else {
|
||||
out.print(" * ");
|
||||
out.println(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
private static int countQuickFixes(Class[] classes, PrintStream out) {
|
||||
int numQuickFixes = 0;
|
||||
for (int i = 0; i < classes.length; i++) {
|
||||
final Class aClass = classes[i];
|
||||
final String className = aClass.getName();
|
||||
try {
|
||||
final LocalInspectionTool inspection = (LocalInspectionTool) aClass.newInstance();
|
||||
if (inspection instanceof BaseInspection) {
|
||||
if (((BaseInspection) inspection).hasQuickFix()) {
|
||||
numQuickFixes++;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (InstantiationException e) {
|
||||
out.print("Couldn't instantiate ");
|
||||
out.println(className);
|
||||
} catch (IllegalAccessException e) {
|
||||
out.print("Couldn't access ");
|
||||
out.println(className);
|
||||
} catch (ClassCastException e) {
|
||||
out.print("Couldn't cast ");
|
||||
out.println(className);
|
||||
}
|
||||
}
|
||||
return numQuickFixes;
|
||||
}
|
||||
|
||||
public static InspectionGadgetsPlugin getInstance() {
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
return (InspectionGadgetsPlugin) application.getComponent(InspectionGadgetsPlugin.class);
|
||||
}
|
||||
|
||||
public String getComponentName() {
|
||||
return "InspectionGadgets";
|
||||
}
|
||||
|
||||
public Class[] getInspectionClasses() {
|
||||
final int numInspections = m_inspectionClasses.size();
|
||||
return (Class[]) m_inspectionClasses.toArray(new Class[numInspections]);
|
||||
}
|
||||
|
||||
public void initComponent() {
|
||||
registerNamingInspections();
|
||||
registerBugInspections();
|
||||
registerCloneInspection();
|
||||
registerConfusingInspections();
|
||||
registerAbstractionInspections();
|
||||
registerClassLayoutInspections();
|
||||
registerImportInspections();
|
||||
registerEncapsulationInspections();
|
||||
registerVisibilityInspections();
|
||||
registerInitializerInspections();
|
||||
registerFinalizationInspections();
|
||||
registerExceptionInspections();
|
||||
registerVerboseInspections();
|
||||
registerStyleInspections();
|
||||
registerSerializationInspections();
|
||||
registerThreadingInspections();
|
||||
registerMethodMetricsInspections();
|
||||
registerClassMetricsInspections();
|
||||
registerPortabilityInspections();
|
||||
registerInternationalInspections();
|
||||
registerPerformanceInspections();
|
||||
registerMaturityInspections();
|
||||
registerJUnitInspections();
|
||||
registerLoggingInspections();
|
||||
registerSecurityInspections();
|
||||
Collections.sort(m_inspectionClasses, new InspectionComparator());
|
||||
}
|
||||
|
||||
private void registerLoggingInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(ClassWithoutLoggerInspection.class);
|
||||
inspectionClasses.add(ClassWithMultipleLoggersInspection.class);
|
||||
inspectionClasses.add(NonStaticFinalLoggerInspection.class);
|
||||
}
|
||||
|
||||
private void registerSecurityInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(DeserializableClassInSecureContextInspection.class);
|
||||
inspectionClasses.add(SerializableClassInSecureContextInspection.class);
|
||||
inspectionClasses.add(CloneableClassInSecureContextInspection.class);
|
||||
inspectionClasses.add(NonStaticInnerClassInSecureContextInspection.class);
|
||||
}
|
||||
|
||||
private void registerImportInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(UnusedImportInspection.class);
|
||||
inspectionClasses.add(RedundantImportInspection.class);
|
||||
inspectionClasses.add(OnDemandImportInspection.class);
|
||||
inspectionClasses.add(SingleClassImportInspection.class);
|
||||
inspectionClasses.add(JavaLangImportInspection.class);
|
||||
inspectionClasses.add(SamePackageImportInspection.class);
|
||||
inspectionClasses.add(StaticImportInspection.class);
|
||||
}
|
||||
|
||||
private void registerNamingInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(ClassNamingConventionInspection.class);
|
||||
inspectionClasses.add(InterfaceNamingConventionInspection.class);
|
||||
inspectionClasses.add(InstanceVariableNamingConventionInspection.class);
|
||||
inspectionClasses.add(StaticVariableNamingConventionInspection.class);
|
||||
inspectionClasses.add(ConstantNamingConventionInspection.class);
|
||||
inspectionClasses.add(InstanceMethodNamingConventionInspection.class);
|
||||
inspectionClasses.add(StaticMethodNamingConventionInspection.class);
|
||||
inspectionClasses.add(LocalVariableNamingConventionInspection.class);
|
||||
inspectionClasses.add(ParameterNamingConventionInspection.class);
|
||||
inspectionClasses.add(ExceptionNameDoesntEndWithExceptionInspection.class);
|
||||
inspectionClasses.add(NonExceptionNameEndsWithExceptionInspection.class);
|
||||
inspectionClasses.add(ClassNamePrefixedWithPackageNameInspection.class);
|
||||
inspectionClasses.add(ClassNameSameAsAncestorNameInspection.class);
|
||||
inspectionClasses.add(MethodNameSameAsClassNameInspection.class);
|
||||
inspectionClasses.add(MethodNameSameAsParentNameInspection.class);
|
||||
inspectionClasses.add(StandardVariableNamesInspection.class);
|
||||
inspectionClasses.add(ConfusingMainMethodInspection.class);
|
||||
inspectionClasses.add(UpperCaseFieldNameNotConstantInspection.class);
|
||||
inspectionClasses.add(DollarSignInNameInspection.class);
|
||||
}
|
||||
|
||||
private void registerBugInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
//inspectionClasses.add(StreamOpenCloseInspection.class);
|
||||
inspectionClasses.add(IntegerDivisionInFloatingPointContextInspection.class);
|
||||
inspectionClasses.add(NonShortCircuitBooleanInspection.class);
|
||||
inspectionClasses.add(ComparisonOfShortAndCharInspection.class);
|
||||
inspectionClasses.add(AssignmentUsedAsConditionInspection.class);
|
||||
inspectionClasses.add(EmptyStatementBodyInspection.class);
|
||||
inspectionClasses.add(EmptyInitializerInspection.class);
|
||||
inspectionClasses.add(EqualsBetweenInconvertibleTypesInspection.class);
|
||||
inspectionClasses.add(BigDecimalEqualsInspection.class);
|
||||
inspectionClasses.add(CovariantCompareToInspection.class);
|
||||
inspectionClasses.add(CovariantEqualsInspection.class);
|
||||
inspectionClasses.add(FloatingPointEqualityInspection.class);
|
||||
inspectionClasses.add(MisspelledCompareToInspection.class);
|
||||
inspectionClasses.add(MisspelledHashcodeInspection.class);
|
||||
inspectionClasses.add(MisspelledEqualsInspection.class);
|
||||
inspectionClasses.add(MisspelledToStringInspection.class);
|
||||
inspectionClasses.add(FallthruInSwitchStatementInspection.class);
|
||||
inspectionClasses.add(SwitchStatementsWithoutDefaultInspection.class);
|
||||
inspectionClasses.add(DefaultNotLastCaseInSwitchInspection.class);
|
||||
inspectionClasses.add(ObjectEqualityInspection.class);
|
||||
inspectionClasses.add(ObjectEqualsNullInspection.class);
|
||||
inspectionClasses.add(StringEqualityInspection.class);
|
||||
inspectionClasses.add(IgnoreResultOfCallInspection.class);
|
||||
inspectionClasses.add(ResultOfObjectAllocationIgnoredInspection.class);
|
||||
inspectionClasses.add(ResultSetIndexZeroInspection.class);
|
||||
inspectionClasses.add(LoopStatementsThatDontLoopInspection.class);
|
||||
inspectionClasses.add(MismatchedArrayReadWriteInspection.class);
|
||||
inspectionClasses.add(MismatchedCollectionQueryUpdateInspection.class);
|
||||
inspectionClasses.add(TextLabelInSwitchStatementInspection.class);
|
||||
inspectionClasses.add(AssignmentToNullInspection.class);
|
||||
inspectionClasses.add(ReturnNullInspection.class);
|
||||
inspectionClasses.add(OctalAndDecimalIntegersMixedInspection.class);
|
||||
inspectionClasses.add(IncompatibleMaskInspection.class);
|
||||
inspectionClasses.add(ForLoopWithMissingComponentInspection.class);
|
||||
inspectionClasses.add(ForLoopThatDoesntUseLoopVariableInspection.class);
|
||||
inspectionClasses.add(InfiniteLoopStatementInspection.class);
|
||||
inspectionClasses.add(InfiniteRecursionInspection.class);
|
||||
inspectionClasses.add(SubtractionInCompareToInspection.class);
|
||||
inspectionClasses.add(EqualsUsesNonFinalVariableInspection.class);
|
||||
inspectionClasses.add(HashCodeUsesNonFinalVariableInspection.class);
|
||||
inspectionClasses.add(CompareToUsesNonFinalVariableInspection.class);
|
||||
}
|
||||
|
||||
private void registerAbstractionInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(DuplicateStringLiteralInspection.class);
|
||||
inspectionClasses.add(FeatureEnvyInspection.class);
|
||||
inspectionClasses.add(LocalVariableOfConcreteClassInspection.class);
|
||||
inspectionClasses.add(RawUseOfParameterizedTypeInspection.class);
|
||||
inspectionClasses.add(InstanceVariableOfConcreteClassInspection.class);
|
||||
inspectionClasses.add(StaticVariableOfConcreteClassInspection.class);
|
||||
inspectionClasses.add(ParameterOfConcreteClassInspection.class);
|
||||
inspectionClasses.add(MethodReturnOfConcreteClassInspection.class);
|
||||
inspectionClasses.add(InstanceofInterfacesInspection.class);
|
||||
inspectionClasses.add(CastToConcreteClassInspection.class);
|
||||
inspectionClasses.add(OverlyStrongTypeCastInspection.class);
|
||||
inspectionClasses.add(DeclareCollectionAsInterfaceInspection.class);
|
||||
inspectionClasses.add(MagicNumberInspection.class);
|
||||
inspectionClasses.add(ClassReferencesSubclassInspection.class);
|
||||
inspectionClasses.add(SwitchStatementInspection.class);
|
||||
inspectionClasses.add(PublicMethodNotExposedInInterfaceInspection.class);
|
||||
inspectionClasses.add(InstanceofThisInspection.class);
|
||||
}
|
||||
|
||||
private void registerClassLayoutInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(FinalClassInspection.class);
|
||||
inspectionClasses.add(EmptyClassInspection.class);
|
||||
inspectionClasses.add(AnonymousInnerClassInspection.class);
|
||||
inspectionClasses.add(LimitedScopeInnerClassInspection.class);
|
||||
inspectionClasses.add(FinalMethodInspection.class);
|
||||
inspectionClasses.add(ClassInitializerInspection.class);
|
||||
inspectionClasses.add(ClassMayBeInterfaceInspection.class);
|
||||
inspectionClasses.add(NonProtectedConstructorInAbstractClassInspection.class);
|
||||
inspectionClasses.add(ClassWithoutConstructorInspection.class);
|
||||
inspectionClasses.add(AbstractClassWithoutAbstractMethodsInspection.class);
|
||||
inspectionClasses.add(FinalMethodInFinalClassInspection.class);
|
||||
inspectionClasses.add(ProtectedMemberInFinalClassInspection.class);
|
||||
inspectionClasses.add(PublicConstructorInNonPublicClassInspection.class);
|
||||
inspectionClasses.add(UtilityClassWithPublicConstructorInspection.class);
|
||||
inspectionClasses.add(UtilityClassWithoutPrivateConstructorInspection.class);
|
||||
inspectionClasses.add(AbstractMethodOverridesConcreteMethodInspection.class);
|
||||
inspectionClasses.add(AbstractMethodOverridesAbstractMethodInspection.class);
|
||||
inspectionClasses.add(AbstractClassExtendsConcreteClassInspection.class);
|
||||
inspectionClasses.add(StaticNonFinalFieldInspection.class);
|
||||
inspectionClasses.add(ConstantDeclaredInAbstractClassInspection.class);
|
||||
inspectionClasses.add(ConstantDeclaredInInterfaceInspection.class);
|
||||
inspectionClasses.add(StaticInheritanceInspection.class);
|
||||
inspectionClasses.add(ClassInTopLevelPackageInspection.class);
|
||||
inspectionClasses.add(UtilityClassInspection.class);
|
||||
inspectionClasses.add(SingletonInspection.class);
|
||||
inspectionClasses.add(InnerClassOnInterfaceInspection.class);
|
||||
inspectionClasses.add(FinalPrivateMethodInspection.class);
|
||||
inspectionClasses.add(NoopMethodInAbstractClassInspection.class);
|
||||
inspectionClasses.add(FinalStaticMethodInspection.class);
|
||||
inspectionClasses.add(ClassWithoutNoArgConstructorInspection.class);
|
||||
inspectionClasses.add(MultipleTopLevelClassesInFileInspection.class);
|
||||
inspectionClasses.add(ClassNameDiffersFromFileNameInspection.class);
|
||||
inspectionClasses.add(MarkerInterfaceInspection.class);
|
||||
}
|
||||
|
||||
private void registerCloneInspection() {
|
||||
m_inspectionClasses.add(CloneableImplementsCloneInspection.class);
|
||||
m_inspectionClasses.add(CloneCallsConstructorsInspection.class);
|
||||
m_inspectionClasses.add(CloneCallsSuperCloneInspection.class);
|
||||
m_inspectionClasses.add(CloneDeclaresCloneNotSupportedInspection.class);
|
||||
|
||||
}
|
||||
|
||||
private void registerVisibilityInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(FieldHidesSuperclassFieldInspection.class);
|
||||
inspectionClasses.add(InnerClassVariableHidesOuterClassVariableInspection.class);
|
||||
inspectionClasses.add(ParameterHidingMemberVariableInspection.class);
|
||||
inspectionClasses.add(LocalVariableHidingMemberVariableInspection.class);
|
||||
inspectionClasses.add(MethodOverridesPrivateMethodInspection.class);
|
||||
inspectionClasses.add(MethodOverridesStaticMethodInspection.class);
|
||||
inspectionClasses.add(MethodOverloadsParentMethodInspection.class);
|
||||
}
|
||||
|
||||
private void registerEncapsulationInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(PublicFieldInspection.class);
|
||||
inspectionClasses.add(PackageVisibleFieldInspection.class);
|
||||
inspectionClasses.add(ProtectedFieldInspection.class);
|
||||
inspectionClasses.add(PublicInnerClassInspection.class);
|
||||
inspectionClasses.add(PackageVisibleInnerClassInspection.class);
|
||||
inspectionClasses.add(ProtectedInnerClassInspection.class);
|
||||
inspectionClasses.add(ReturnOfCollectionFieldInspection.class);
|
||||
inspectionClasses.add(ReturnOfDateFieldInspection.class);
|
||||
inspectionClasses.add(AssignmentToCollectionFieldFromParameterInspection.class);
|
||||
inspectionClasses.add(AssignmentToDateFieldFromParameterInspection.class);
|
||||
}
|
||||
|
||||
private void registerInitializerInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(StaticVariableInitializationInspection.class);
|
||||
inspectionClasses.add(InstanceVariableInitializationInspection.class);
|
||||
inspectionClasses.add(AbstractMethodCallInConstructorInspection.class);
|
||||
inspectionClasses.add(OverridableMethodCallInConstructorInspection.class);
|
||||
inspectionClasses.add(ThisEscapedInConstructorInspection.class);
|
||||
inspectionClasses.add(StaticVariableUninitializedUseInspection.class);
|
||||
inspectionClasses.add(InstanceVariableUninitializedUseInspection.class);
|
||||
}
|
||||
|
||||
private void registerConfusingInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(ClassEscapesItsScopeInspection.class);
|
||||
inspectionClasses.add(ConfusingFloatingPointLiteralInspection.class);
|
||||
inspectionClasses.add(OverlyComplexArithmeticExpressionInspection.class);
|
||||
inspectionClasses.add(OverlyComplexBooleanExpressionInspection.class);
|
||||
inspectionClasses.add(AssignmentToMethodParameterInspection.class);
|
||||
inspectionClasses.add(AssignmentToCatchBlockParameterInspection.class);
|
||||
inspectionClasses.add(AssignmentToForLoopParameterInspection.class);
|
||||
inspectionClasses.add(NestedAssignmentInspection.class);
|
||||
inspectionClasses.add(BreakStatementInspection.class);
|
||||
inspectionClasses.add(BreakStatementWithLabelInspection.class);
|
||||
inspectionClasses.add(ContinueStatementInspection.class);
|
||||
inspectionClasses.add(ContinueStatementWithLabelInspection.class);
|
||||
inspectionClasses.add(ConditionalExpressionInspection.class);
|
||||
inspectionClasses.add(NestedConditionalExpressionInspection.class);
|
||||
inspectionClasses.add(LongLiteralsEndingWithLowercaseLInspection.class);
|
||||
inspectionClasses.add(IncrementDecrementUsedAsExpressionInspection.class);
|
||||
inspectionClasses.add(IfStatementWithTooManyBranchesInspection.class);
|
||||
inspectionClasses.add(SwitchStatementWithTooManyBranchesInspection.class);
|
||||
inspectionClasses.add(SwitchStatementWithTooFewBranchesInspection.class);
|
||||
inspectionClasses.add(SwitchStatementDensityInspection.class);
|
||||
inspectionClasses.add(NestedSwitchStatementInspection.class);
|
||||
inspectionClasses.add(ChainedMethodCallInspection.class);
|
||||
inspectionClasses.add(NestedMethodCallInspection.class);
|
||||
inspectionClasses.add(OctalLiteralInspection.class);
|
||||
inspectionClasses.add(ChainedEqualityInspection.class);
|
||||
inspectionClasses.add(ConfusingOctalEscapeInspection.class);
|
||||
inspectionClasses.add(MethodNamesDifferOnlyByCaseInspection.class);
|
||||
inspectionClasses.add(OverloadedMethodsWithSameNumberOfParametersInspection.class);
|
||||
inspectionClasses.add(ImplicitNumericConversionInspection.class);
|
||||
inspectionClasses.add(ImplicitCallToSuperInspection.class);
|
||||
inspectionClasses.add(RefusedBequestInspection.class);
|
||||
inspectionClasses.add(CastThatLosesPrecisionInspection.class);
|
||||
inspectionClasses.add(NegatedIfElseInspection.class);
|
||||
inspectionClasses.add(NegatedConditionalInspection.class);
|
||||
inspectionClasses.add(ConfusingElseInspection.class);
|
||||
inspectionClasses.add(SwitchStatementWithConfusingDeclarationInspection.class);
|
||||
}
|
||||
|
||||
private void registerVerboseInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(UnnecessaryLabelOnBreakStatementInspection.class);
|
||||
inspectionClasses.add(UnnecessaryLabelOnContinueStatementInspection.class);
|
||||
inspectionClasses.add(PointlessBooleanExpressionInspection.class);
|
||||
inspectionClasses.add(ReplaceAssignmentWithOperatorAssignmentInspection.class);
|
||||
inspectionClasses.add(TrivialIfInspection.class);
|
||||
inspectionClasses.add(UnnecessaryConditionalExpressionInspection.class);
|
||||
inspectionClasses.add(UnnecessaryParenthesesInspection.class);
|
||||
inspectionClasses.add(UnnecessaryThisInspection.class);
|
||||
inspectionClasses.add(UnnecessaryBlockStatementInspection.class);
|
||||
inspectionClasses.add(UnnecessaryInterfaceModifierInspection.class);
|
||||
inspectionClasses.add(UnnecessaryReturnInspection.class);
|
||||
inspectionClasses.add(UnnecessaryContinueInspection.class);
|
||||
inspectionClasses.add(UnnecessarySemicolonInspection.class);
|
||||
inspectionClasses.add(UnnecessaryFullyQualifiedNameInspection.class);
|
||||
inspectionClasses.add(UnnecessaryQualifierForThisInspection.class);
|
||||
inspectionClasses.add(UnusedLabelInspection.class);
|
||||
inspectionClasses.add(RedundantFieldInitializationInspection.class);
|
||||
inspectionClasses.add(RedundantImplementsInspection.class);
|
||||
inspectionClasses.add(ExtendsObjectInspection.class);
|
||||
inspectionClasses.add(TypeParameterExtendsObjectInspection.class);
|
||||
inspectionClasses.add(PointlessArithmeticExpressionInspection.class);
|
||||
inspectionClasses.add(PointlessBitwiseExpressionInspection.class);
|
||||
inspectionClasses.add(UnnecessarySuperConstructorInspection.class);
|
||||
inspectionClasses.add(ForLoopReplaceableByWhileInspection.class);
|
||||
inspectionClasses.add(UnnecessaryDefaultInspection.class);
|
||||
inspectionClasses.add(UnnecessaryBoxingInspection.class);
|
||||
inspectionClasses.add(UnnecessaryUnboxingInspection.class);
|
||||
inspectionClasses.add(UnnecessaryFinalOnParameterInspection.class);
|
||||
inspectionClasses.add(UnnecessaryFinalOnLocalVariableInspection.class);
|
||||
inspectionClasses.add(ForCanBeForeachInspection.class);
|
||||
}
|
||||
|
||||
private void registerStyleInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(ReturnThisInspection.class);
|
||||
inspectionClasses.add(ConstantOnLHSOfComparisonInspection.class);
|
||||
inspectionClasses.add(ConstantOnRHSOfComparisonInspection.class);
|
||||
inspectionClasses.add(LiteralAsArgToStringEqualsInspection.class);
|
||||
inspectionClasses.add(MissortedModifiersInspection.class);
|
||||
inspectionClasses.add(CStyleArrayDeclarationInspection.class);
|
||||
inspectionClasses.add(MultipleDeclarationInspection.class);
|
||||
inspectionClasses.add(MultipleTypedDeclarationInspection.class);
|
||||
inspectionClasses.add(UnqualifiedStaticUsageInspection.class);
|
||||
inspectionClasses.add(UnnecessarilyQualifiedStaticUsageInspection.class);
|
||||
}
|
||||
|
||||
private void registerExceptionInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(CatchGenericClassInspection.class);
|
||||
inspectionClasses.add(EmptyCatchBlockInspection.class);
|
||||
inspectionClasses.add(UnusedCatchParameterInspection.class);
|
||||
inspectionClasses.add(EmptyFinallyBlockInspection.class);
|
||||
inspectionClasses.add(EmptyTryBlockInspection.class);
|
||||
inspectionClasses.add(ThrowFromFinallyBlockInspection.class);
|
||||
inspectionClasses.add(ThrowCaughtLocallyInspection.class);
|
||||
inspectionClasses.add(ReturnFromFinallyBlockInspection.class);
|
||||
inspectionClasses.add(ContinueOrBreakFromFinallyBlockInspection.class);
|
||||
inspectionClasses.add(ThrowGenericClassInspection.class);
|
||||
inspectionClasses.add(TooBroadCatchInspection.class);
|
||||
inspectionClasses.add(CheckedExceptionClassInspection.class);
|
||||
inspectionClasses.add(UncheckedExceptionClassInspection.class);
|
||||
inspectionClasses.add(ThreadDeathRethrownInspection.class);
|
||||
inspectionClasses.add(ErrorRethrownInspection.class);
|
||||
inspectionClasses.add(NestedTryStatementInspection.class);
|
||||
inspectionClasses.add(ExceptionFromCatchWhichDoesntWrapInspection.class);
|
||||
inspectionClasses.add(InstanceofCatchParameterInspection.class);
|
||||
}
|
||||
|
||||
private void registerFinalizationInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(FinalizeInspection.class);
|
||||
inspectionClasses.add(FinalizeNotProtectedInspection.class);
|
||||
inspectionClasses.add(FinalizeCallsSuperFinalizeInspection.class);
|
||||
inspectionClasses.add(NoExplicitFinalizeCallsInspection.class);
|
||||
}
|
||||
|
||||
private void registerSerializationInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(SerializableHasSerializationMethodsInspection.class);
|
||||
inspectionClasses.add(SerializableHasSerialVersionUIDFieldInspection.class);
|
||||
inspectionClasses.add(ReadObjectInitializationInspection.class);
|
||||
inspectionClasses.add(ReadObjectAndWriteObjectPrivateInspection.class);
|
||||
inspectionClasses.add(SerialVersionUIDNotStaticFinalInspection.class);
|
||||
inspectionClasses.add(ReadResolveAndWriteReplaceProtectedInspection.class);
|
||||
inspectionClasses.add(TransientFieldInNonSerializableClassInspection.class);
|
||||
inspectionClasses.add(SerializableWithUnconstructableAncestorInspection.class);
|
||||
inspectionClasses.add(NonSerializableWithSerializationMethodsInspection.class);
|
||||
inspectionClasses.add(ExternalizableWithSerializationMethodsInspection.class);
|
||||
inspectionClasses.add(NonSerializableWithSerialVersionUIDFieldInspection.class);
|
||||
inspectionClasses.add(SerializableInnerClassHasSerialVersionUIDFieldInspection.class);
|
||||
inspectionClasses.add(SerializableInnerClassWithNonSerializableOuterClassInspection.class);
|
||||
}
|
||||
|
||||
private void registerThreadingInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(DoubleCheckedLockingInspection.class);
|
||||
inspectionClasses.add(BusyWaitInspection.class);
|
||||
inspectionClasses.add(ObjectNotifyInspection.class);
|
||||
inspectionClasses.add(NakedNotifyInspection.class);
|
||||
inspectionClasses.add(UnconditionalWaitInspection.class);
|
||||
inspectionClasses.add(WhileLoopSpinsOnFieldInspection.class);
|
||||
inspectionClasses.add(WaitNotInLoopInspection.class);
|
||||
inspectionClasses.add(VolatileLongOrDoubleFieldInspection.class);
|
||||
inspectionClasses.add(WaitNotInSynchronizedContextInspection.class);
|
||||
inspectionClasses.add(WaitWhileHoldingTwoLocksInspection.class);
|
||||
inspectionClasses.add(NotifyNotInSynchronizedContextInspection.class);
|
||||
inspectionClasses.add(ThreadRunInspection.class);
|
||||
inspectionClasses.add(ThreadStartInConstructionInspection.class);
|
||||
inspectionClasses.add(SynchronizedMethodInspection.class);
|
||||
inspectionClasses.add(SynchronizeOnLockInspection.class);
|
||||
inspectionClasses.add(SynchronizeOnNonFinalFieldInspection.class);
|
||||
inspectionClasses.add(SynchronizeOnThisInspection.class);
|
||||
inspectionClasses.add(NestedSynchronizedStatementInspection.class);
|
||||
inspectionClasses.add(EmptySynchronizedStatementInspection.class);
|
||||
inspectionClasses.add(NonSynchronizedMethodOverridesSynchronizedMethodInspection.class);
|
||||
inspectionClasses.add(PublicFieldAccessedInSynchronizedContextInspection.class);
|
||||
inspectionClasses.add(FieldAccessedSynchronizedAndUnsynchronizedInspection.class);
|
||||
}
|
||||
|
||||
private void registerMethodMetricsInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(ThreeNegationsPerMethodInspection.class);
|
||||
inspectionClasses.add(MethodWithMultipleLoopsInspection.class);
|
||||
inspectionClasses.add(MultipleReturnPointsPerMethodInspection.class);
|
||||
inspectionClasses.add(ParametersPerMethodInspection.class);
|
||||
inspectionClasses.add(CyclomaticComplexityInspection.class);
|
||||
inspectionClasses.add(NestingDepthInspection.class);
|
||||
inspectionClasses.add(NonCommentSourceStatementsInspection.class);
|
||||
inspectionClasses.add(MethodCouplingInspection.class);
|
||||
}
|
||||
|
||||
private void registerClassMetricsInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(AnonymousClassComplexityInspection.class);
|
||||
inspectionClasses.add(AnonymousClassMethodCountInspection.class);
|
||||
inspectionClasses.add(ClassComplexityInspection.class);
|
||||
inspectionClasses.add(ClassInheritanceDepthInspection.class);
|
||||
inspectionClasses.add(ClassNestingDepthInspection.class);
|
||||
inspectionClasses.add(ClassCouplingInspection.class);
|
||||
inspectionClasses.add(ConstructorCountInspection.class);
|
||||
inspectionClasses.add(MethodCountInspection.class);
|
||||
inspectionClasses.add(FieldCountInspection.class);
|
||||
}
|
||||
|
||||
private void registerPortabilityInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(RuntimeExecInspection.class);
|
||||
inspectionClasses.add(SystemExitInspection.class);
|
||||
inspectionClasses.add(SystemGetenvInspection.class);
|
||||
inspectionClasses.add(HardcodedLineSeparatorsInspection.class);
|
||||
inspectionClasses.add(HardcodedFileSeparatorsInspection.class);
|
||||
inspectionClasses.add(NativeMethodsInspection.class);
|
||||
inspectionClasses.add(AssertAsNameInspection.class);
|
||||
inspectionClasses.add(EnumAsNameInspection.class);
|
||||
inspectionClasses.add(AssertStatementInspection.class);
|
||||
inspectionClasses.add(AutoBoxingInspection.class);
|
||||
inspectionClasses.add(AutoUnboxingInspection.class);
|
||||
inspectionClasses.add(VarargParameterInspection.class);
|
||||
inspectionClasses.add(ForeachStatementInspection.class);
|
||||
inspectionClasses.add(EnumClassInspection.class);
|
||||
inspectionClasses.add(AnnotationClassInspection.class);
|
||||
inspectionClasses.add(AnnotationInspection.class);
|
||||
inspectionClasses.add(UseOfSunClassesInspection.class);
|
||||
}
|
||||
|
||||
private void registerInternationalInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(StringLiteralInspection.class);
|
||||
inspectionClasses.add(CharacterComparisonInspection.class);
|
||||
inspectionClasses.add(MagicCharacterInspection.class);
|
||||
inspectionClasses.add(NumericToStringInspection.class);
|
||||
inspectionClasses.add(DateToStringInspection.class);
|
||||
inspectionClasses.add(TimeToStringInspection.class);
|
||||
inspectionClasses.add(StringCompareToInspection.class);
|
||||
inspectionClasses.add(StringEqualsIgnoreCaseInspection.class);
|
||||
inspectionClasses.add(StringEqualsInspection.class);
|
||||
inspectionClasses.add(StringConcatenationInspection.class);
|
||||
inspectionClasses.add(StringTokenizerInspection.class);
|
||||
inspectionClasses.add(StringToUpperWithoutLocaleInspection.class);
|
||||
}
|
||||
|
||||
private void registerPerformanceInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(ObjectAllocationInLoopInspection.class);
|
||||
inspectionClasses.add(UnnecessaryTemporaryOnConversionToStringInspection.class);
|
||||
inspectionClasses.add(UnnecessaryTemporaryOnConversionFromStringInspection.class);
|
||||
inspectionClasses.add(FieldMayBeStaticInspection.class);
|
||||
inspectionClasses.add(MethodMayBeStaticInspection.class);
|
||||
inspectionClasses.add(InnerClassMayBeStaticInspection.class);
|
||||
inspectionClasses.add(StringBufferMustHaveInitialCapacityInspection.class);
|
||||
inspectionClasses.add(StringBufferReplaceableByStringBuilderInspection.class);
|
||||
inspectionClasses.add(StringBufferReplaceableByStringInspection.class);
|
||||
inspectionClasses.add(StringReplaceableByStringBufferInspection.class);
|
||||
inspectionClasses.add(CollectionsMustHaveInitialCapacityInspection.class);
|
||||
inspectionClasses.add(StringConcatenationInLoopsInspection.class);
|
||||
inspectionClasses.add(MultiplyOrDivideByPowerOfTwoInspection.class);
|
||||
inspectionClasses.add(LengthOneStringsInConcatenationInspection.class);
|
||||
inspectionClasses.add(BooleanConstructorInspection.class);
|
||||
inspectionClasses.add(StringToStringInspection.class);
|
||||
inspectionClasses.add(StringConstructorInspection.class);
|
||||
inspectionClasses.add(StringBufferToStringInConcatenationInspection.class);
|
||||
inspectionClasses.add(TailRecursionInspection.class);
|
||||
inspectionClasses.add(TrivialStringConcatenationInspection.class);
|
||||
inspectionClasses.add(SystemGCInspection.class);
|
||||
inspectionClasses.add(SingleCharacterStartsWithInspection.class);
|
||||
inspectionClasses.add(StringEqualsEmptyStringInspection.class);
|
||||
inspectionClasses.add(FieldRepeatedlyAccessedInspection.class);
|
||||
inspectionClasses.add(ManualArrayCopyInspection.class);
|
||||
inspectionClasses.add(JavaLangReflectInspection.class);
|
||||
inspectionClasses.add(StaticCollectionInspection.class);
|
||||
inspectionClasses.add(ZeroLengthArrayInitializationInspection.class);
|
||||
}
|
||||
|
||||
private void registerMaturityInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(SystemOutErrInspection.class);
|
||||
inspectionClasses.add(ThrowablePrintStackTraceInspection.class);
|
||||
inspectionClasses.add(ThreadDumpStackInspection.class);
|
||||
inspectionClasses.add(ClassWithoutToStringInspection.class);
|
||||
inspectionClasses.add(ObsoleteCollectionInspection.class);
|
||||
}
|
||||
|
||||
private void registerJUnitInspections() {
|
||||
final List inspectionClasses = m_inspectionClasses;
|
||||
inspectionClasses.add(AssertsWithoutMessagesInspection.class);
|
||||
inspectionClasses.add(TestCaseWithConstructorInspection.class);
|
||||
inspectionClasses.add(MisspelledSetUpInspection.class);
|
||||
inspectionClasses.add(MisspelledTearDownInspection.class);
|
||||
inspectionClasses.add(StaticSuiteInspection.class);
|
||||
inspectionClasses.add(SetupCallsSuperSetupInspection.class);
|
||||
inspectionClasses.add(TeardownCallsSuperTeardownInspection.class);
|
||||
inspectionClasses.add(SetupIsPublicVoidNoArgInspection.class);
|
||||
inspectionClasses.add(TeardownIsPublicVoidNoArgInspection.class);
|
||||
inspectionClasses.add(TestMethodIsPublicVoidNoArgInspection.class);
|
||||
inspectionClasses.add(TestMethodWithoutAssertionInspection.class);
|
||||
inspectionClasses.add(TestCaseWithNoTestMethodsInspection.class);
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
|
||||
}
|
||||
|
||||
public InspectionGadgetsConfig getConfig() {
|
||||
return m_config;
|
||||
}
|
||||
|
||||
public void readExternal(Element element) throws InvalidDataException {
|
||||
m_config.readExternal(element);
|
||||
}
|
||||
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
m_config.writeExternal(element);
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
final InspectionGadgetsPlugin instance = getInstance();
|
||||
final InspectionGadgetsConfig config = instance.getConfig();
|
||||
return config.isEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* (c) 2004 Carp Technologies BV
|
||||
* Hengelosestraat 705, 7521PA Enschede
|
||||
* Created: Feb 3, 2004, 5:44:43 PM
|
||||
*/
|
||||
package com.siyeh.ig;
|
||||
|
||||
import javax.swing.text.DefaultFormatter;
|
||||
import java.text.ParseException;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
/**
|
||||
* @author <A href="bas@carp-technologies.nl">Bas Leijdekkers</a>
|
||||
*/
|
||||
public class RegExFormatter extends DefaultFormatter {
|
||||
public RegExFormatter() {
|
||||
super();
|
||||
setOverwriteMode(false);
|
||||
}
|
||||
|
||||
public Object stringToValue(String text) throws ParseException {
|
||||
try {
|
||||
return Pattern.compile(text);
|
||||
} catch (final PatternSyntaxException e) {
|
||||
throw new ParseException(e.getMessage(), e.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public String valueToString(Object value) throws ParseException {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return ((Pattern) value).pattern();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
|
||||
import javax.swing.InputVerifier;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* @author <A href="bas@carp-technologies.nl">Bas Leijdekkers</a>
|
||||
*/
|
||||
public class RegExInputVerifier extends InputVerifier {
|
||||
public boolean verify(JComponent input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean shouldYieldFocus(JComponent input) {
|
||||
if (input instanceof JFormattedTextField) {
|
||||
final JFormattedTextField ftf = (JFormattedTextField) input;
|
||||
final JFormattedTextField.AbstractFormatter formatter = ftf.getFormatter();
|
||||
if (formatter != null) {
|
||||
try {
|
||||
formatter.stringToValue(ftf.getText());
|
||||
} catch (final ParseException e) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
Messages.showErrorDialog(e.getMessage(), "Malformed Naming Pattern");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiTypeCastExpression;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class CastToConcreteClassInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Cast to a concrete class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Cast to concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new CastToConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class CastToConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
|
||||
private CastToConcreteClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitTypeCastExpression(PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
final PsiTypeElement typeElement = expression.getCastType();
|
||||
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.psiutils.LibraryUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class ClassAccessVisitor extends PsiRecursiveElementVisitor {
|
||||
private final Map m_accessCounts = new HashMap(2);
|
||||
private final Set m_overAccessedClasses = new HashSet(2);
|
||||
private static final Integer ONE = new Integer(1);
|
||||
private static final Integer TWO = new Integer(2);
|
||||
private PsiClass currentClass;
|
||||
|
||||
ClassAccessVisitor(PsiClass currentClass) {
|
||||
super();
|
||||
this.currentClass = currentClass;
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression ref) {
|
||||
final PsiExpression qualifier = ref.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
qualifier.accept(this);
|
||||
}
|
||||
final PsiReferenceParameterList typeParameters = ref.getParameterList();
|
||||
if (typeParameters != null) {
|
||||
typeParameters.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiMethod method = expression.resolveMethod();
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiClass calledClass = method.getContainingClass();
|
||||
if (currentClass.equals(calledClass)) {
|
||||
return;
|
||||
}
|
||||
if (currentClass.isInheritor(calledClass, true)) {
|
||||
return;
|
||||
}
|
||||
if (PsiTreeUtil.isAncestor(currentClass, calledClass, true)) {
|
||||
return;
|
||||
}
|
||||
if (PsiTreeUtil.isAncestor(calledClass, currentClass, true)) {
|
||||
return;
|
||||
}
|
||||
if (LibraryUtil.classIsInLibrary(calledClass)) {
|
||||
return;
|
||||
}
|
||||
final Set overAccessedClasses = m_overAccessedClasses;
|
||||
if (overAccessedClasses.contains(calledClass)) {
|
||||
return;
|
||||
}
|
||||
final Map accessCounts = m_accessCounts;
|
||||
final Integer count = (Integer) accessCounts.get(calledClass);
|
||||
if (count == null) {
|
||||
accessCounts.put(calledClass, ONE);
|
||||
} else if (count.equals(ONE)) {
|
||||
accessCounts.put(calledClass, TWO);
|
||||
} else {
|
||||
overAccessedClasses.add(calledClass);
|
||||
}
|
||||
}
|
||||
|
||||
public Set getOveraccessedClasses() {
|
||||
return Collections.unmodifiableSet(m_overAccessedClasses);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.CollectionUtils;
|
||||
|
||||
public class ClassReferencesSubclassInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Class references one of its subclasses";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement classRef) {
|
||||
final PsiClass containingClass =
|
||||
ClassUtils.getContainingClass(classRef);
|
||||
final String containingClassName = containingClass.getName();
|
||||
return "Class " + containingClassName + " references subclass #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ClassReferencesSubclassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ClassReferencesSubclassVisitor extends BaseInspectionVisitor {
|
||||
private boolean m_inClass = false;
|
||||
|
||||
private ClassReferencesSubclassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
final boolean wasInClass = m_inClass;
|
||||
if (!m_inClass) {
|
||||
|
||||
m_inClass = true;
|
||||
super.visitClass(aClass);
|
||||
}
|
||||
m_inClass = wasInClass;
|
||||
}
|
||||
|
||||
public void visitVariable(PsiVariable variable) {
|
||||
final PsiType type = variable.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType componentType = type.getDeepComponentType();
|
||||
if (!(componentType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiClassType classType = (PsiClassType) componentType;
|
||||
|
||||
final PsiClass containingClass =
|
||||
ClassUtils.getContainingClass(variable);
|
||||
if (!isSubclass(classType, containingClass)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement typeElement = variable.getTypeElement();
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
super.visitMethod(method);
|
||||
final PsiType type = method.getReturnType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType componentType = type.getDeepComponentType();
|
||||
if (!(componentType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType) componentType;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (!isSubclass(classType, containingClass)) {
|
||||
return;
|
||||
}
|
||||
if (!CollectionUtils.isCollectionClass(type)) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = method.getReturnTypeElement();
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
public void visitInstanceOfExpression(PsiInstanceOfExpression exp) {
|
||||
super.visitInstanceOfExpression(exp);
|
||||
final PsiTypeElement typeElement = exp.getCheckType();
|
||||
if (typeElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = typeElement.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType componentType = type.getDeepComponentType();
|
||||
if (!(componentType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType) componentType;
|
||||
final PsiClass containingClass =
|
||||
ClassUtils.getContainingClass(exp);
|
||||
if (!isSubclass(classType, containingClass)) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
public void visitTypeCastExpression(PsiTypeCastExpression exp) {
|
||||
super.visitTypeCastExpression(exp);
|
||||
final PsiTypeElement typeElement = exp.getCastType();
|
||||
if (typeElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = typeElement.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType componentType = type.getDeepComponentType();
|
||||
if (!(componentType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType) componentType;
|
||||
final PsiClass containingClass =
|
||||
ClassUtils.getContainingClass(exp);
|
||||
if (!isSubclass(classType, containingClass)) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression exp) {
|
||||
super.visitClassObjectAccessExpression(exp);
|
||||
final PsiTypeElement typeElement = exp.getOperand();
|
||||
if (typeElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = typeElement.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType componentType = type.getDeepComponentType();
|
||||
if (!(componentType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClassType classType = (PsiClassType) componentType;
|
||||
final PsiClass containingClass =
|
||||
ClassUtils.getContainingClass(exp);
|
||||
if (!isSubclass(classType, containingClass)) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
private static boolean isSubclass(PsiClassType childClass, PsiClass parent) {
|
||||
final PsiClass child = childClass.resolve();
|
||||
if (child == null) {
|
||||
return false;
|
||||
}
|
||||
return child.isInheritor(parent, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.psiutils.LibraryUtil;
|
||||
|
||||
public class ConcreteClassUtil {
|
||||
private ConcreteClassUtil() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static boolean typeIsConcreteClass(PsiTypeElement typeElement) {
|
||||
if (typeElement == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType type = typeElement.getType();
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType baseType = type.getDeepComponentType();
|
||||
if (baseType == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(baseType instanceof PsiClassType)) {
|
||||
return false;
|
||||
}
|
||||
final PsiClass aClass = ((PsiClassType) baseType).resolve();
|
||||
if (aClass == null) {
|
||||
return false;
|
||||
}
|
||||
if (aClass.isInterface() || aClass.isEnum()|| aClass.isAnnotationType()) {
|
||||
return false;
|
||||
}
|
||||
if (LibraryUtil.classIsInLibrary(aClass)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.VariableInspection;
|
||||
import com.siyeh.ig.psiutils.CollectionUtils;
|
||||
|
||||
public class DeclareCollectionAsInterfaceInspection extends VariableInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Collection declared by class, not interface";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final String type = location.getText();
|
||||
final String interfaceName = CollectionUtils.getInterfaceForClass(type);
|
||||
return "Declaration of #ref should probably be weakened to " + interfaceName + " #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new DeclareCollectionAsInterfaceVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class DeclareCollectionAsInterfaceVisitor extends BaseInspectionVisitor {
|
||||
private DeclareCollectionAsInterfaceVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitVariable(PsiVariable variable) {
|
||||
final PsiType type = variable.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
if (!CollectionUtils.isCollectionClass(type)) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = variable.getTypeElement();
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
super.visitMethod(method);
|
||||
final PsiType type = method.getReturnType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
if (!CollectionUtils.isCollectionClass(type)) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = method.getReturnTypeElement();
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiIdentifier;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class FeatureEnvyInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Feature Envy";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(Object arg) {
|
||||
final String className = ((PsiNamedElement) arg).getName();
|
||||
return "Class " + className + " accessed repeatedly in method #ref #loc";
|
||||
}
|
||||
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InstanceVariableRepeatedlyAccessedVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InstanceVariableRepeatedlyAccessedVisitor extends BaseInspectionVisitor {
|
||||
private InstanceVariableRepeatedlyAccessedVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
final PsiIdentifier nameIdentifier = method.getNameIdentifier();
|
||||
if (nameIdentifier == null) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
final ClassAccessVisitor visitor = new ClassAccessVisitor(containingClass);
|
||||
method.accept(visitor);
|
||||
final Set overaccessedClasses = visitor.getOveraccessedClasses();
|
||||
for (Iterator iterator = overaccessedClasses.iterator(); iterator.hasNext();) {
|
||||
final PsiClass aClass = (PsiClass) iterator.next();
|
||||
registerError(nameIdentifier, aClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.FieldInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class InstanceVariableOfConcreteClassInspection extends FieldInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Concrete class for instance variable";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(Object arg) {
|
||||
return "Instance variable " + arg + " of concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InstanceVariableOfConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InstanceVariableOfConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
private InstanceVariableOfConcreteClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
super.visitField(field);
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = field.getTypeElement();
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
final String variableName = field.getName();
|
||||
registerError(typeElement, variableName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiInstanceOfExpression;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class InstanceofInterfacesInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'instanceof' a concrete class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'instanceof' concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InstanceofInterfacesVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InstanceofInterfacesVisitor extends BaseInspectionVisitor {
|
||||
private InstanceofInterfacesVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
|
||||
super.visitInstanceOfExpression(expression);
|
||||
final PsiTypeElement typeElement = expression.getCheckType();
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class InstanceofThisInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'instanceof' check for 'this'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'instanceof' check for #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InstanceofThisVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InstanceofThisVisitor extends BaseInspectionVisitor {
|
||||
private InstanceofThisVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitThisExpression(PsiThisExpression thisValue) {
|
||||
super.visitThisExpression(thisValue);
|
||||
if (thisValue.getQualifier() != null) {
|
||||
return;
|
||||
}
|
||||
PsiElement parent = thisValue.getParent();
|
||||
while (parent != null &&
|
||||
(parent instanceof PsiParenthesizedExpression ||
|
||||
parent instanceof PsiConditionalExpression ||
|
||||
parent instanceof PsiTypeCastExpression)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent == null || !(parent instanceof PsiInstanceOfExpression)) {
|
||||
return;
|
||||
}
|
||||
registerError(thisValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiLocalVariable;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class LocalVariableOfConcreteClassInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Concrete class for local variable";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(Object arg) {
|
||||
return "Local variable " + arg + " of concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new LocalVariableOfConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class LocalVariableOfConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
private LocalVariableOfConcreteClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitLocalVariable(PsiLocalVariable variable) {
|
||||
super.visitLocalVariable(variable);
|
||||
final PsiTypeElement typeElement = variable.getTypeElement();
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
final String variableName = variable.getName();
|
||||
registerError(typeElement, variableName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.IntroduceConstantFix;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MagicNumberInspection extends ExpressionInspection {
|
||||
|
||||
private static final int NUM_SPECIAL_CASE_LITERALS = 22;
|
||||
private static final String[] s_specialCaseLiteralArray =
|
||||
new String[]{
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "0L",
|
||||
"1L", "2L", "0l", "1l", "2l", "0.0", "1.0", "0.0F", "1.0F", "0.0f", "1.0f"
|
||||
};
|
||||
private static final Set s_specialCaseLiterals = new HashSet(NUM_SPECIAL_CASE_LITERALS);
|
||||
private final IntroduceConstantFix fix = new IntroduceConstantFix();
|
||||
|
||||
static {
|
||||
for (int i = 0; i < s_specialCaseLiteralArray.length; i++) {
|
||||
s_specialCaseLiterals.add(s_specialCaseLiteralArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "\"Magic number\"";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Magic number '#ref' #loc";
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MagicNumberVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MagicNumberVisitor extends BaseInspectionVisitor {
|
||||
private MagicNumberVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitLiteralExpression(PsiLiteralExpression expression) {
|
||||
super.visitLiteralExpression(expression);
|
||||
final PsiType type = expression.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
if (!ClassUtils.isPrimitiveNumericType(type)) {
|
||||
return;
|
||||
}
|
||||
if (type.equals(PsiType.CHAR)) {
|
||||
return;
|
||||
}
|
||||
final String text = expression.getText();
|
||||
if (text == null) {
|
||||
return;
|
||||
}
|
||||
if (isSpecialCase(text)) {
|
||||
return;
|
||||
}
|
||||
if (isDeclaredConstant(expression)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
private static boolean isSpecialCase(String text) {
|
||||
return s_specialCaseLiterals.contains(text);
|
||||
}
|
||||
|
||||
private static boolean isDeclaredConstant(PsiLiteralExpression expression) {
|
||||
final PsiField field =
|
||||
(PsiField) PsiTreeUtil.getParentOfType(expression, PsiField.class);
|
||||
if (field == null) {
|
||||
return false;
|
||||
}
|
||||
if (!field.hasModifierProperty(PsiModifier.STATIC) ||
|
||||
!field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return false;
|
||||
}
|
||||
final PsiType type = field.getType();
|
||||
if (!ClassUtils.isImmutable(type)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
|
||||
public class MethodReturnOfConcreteClassInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Concrete class for method return";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
protected String buildErrorString(PsiElement location) {
|
||||
return "Method returns a concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MethodReturnOfConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MethodReturnOfConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
private MethodReturnOfConcreteClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
super.visitMethod(method);
|
||||
if (method.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = method.getReturnTypeElement();
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
|
||||
|
||||
public class OverlyStrongTypeCastInspection extends ExpressionInspection {
|
||||
private final OverlyStringCastFix fix = new OverlyStringCastFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Overly-strong type cast";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Cast to #ref can be weakened #loc";
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class OverlyStringCastFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Weaken overly-strong cast";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement castTypeElement = descriptor.getPsiElement();
|
||||
final PsiTypeCastExpression expression =
|
||||
(PsiTypeCastExpression) castTypeElement.getParent();
|
||||
final PsiType expectedType =
|
||||
ExpectedTypeUtils.findExpectedType(expression);
|
||||
final String newExpression = '(' + expectedType.getPresentableText() + ')' + expression.getOperand().getText();
|
||||
replaceExpression(project, expression, newExpression);
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new OverlyStrongTypeCastVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class OverlyStrongTypeCastVisitor extends BaseInspectionVisitor {
|
||||
private OverlyStrongTypeCastVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitTypeCastExpression(PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
final PsiExpression operand = expression.getOperand();
|
||||
if (operand == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType operandType = operand.getType();
|
||||
if (operandType == null) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = expression.getCastType();
|
||||
if (typeElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = typeElement.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType expectedType =
|
||||
ExpectedTypeUtils.findExpectedType(expression);
|
||||
if (expectedType == null) {
|
||||
return;
|
||||
}
|
||||
if (expectedType.equals(type)) {
|
||||
return;
|
||||
}
|
||||
if (expectedType.isAssignableFrom(operandType)) {
|
||||
return; //then it's redundant, and caught by the built-in exception
|
||||
}
|
||||
|
||||
if (ClassUtils.isPrimitiveNumericType(type) ||
|
||||
ClassUtils.isPrimitiveNumericType(expectedType)) {
|
||||
return;
|
||||
}
|
||||
if (TypeConversionUtil.isPrimitiveWrapper(type.getCanonicalText()) ||
|
||||
TypeConversionUtil.isPrimitiveWrapper(type.getCanonicalText())) {
|
||||
return;
|
||||
}
|
||||
registerError(typeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.PsiTryStatement;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
|
||||
public class ParameterOfConcreteClassInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Concrete class for method parameter";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(Object arg) {
|
||||
return "Parameter " + arg + " of concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new LocalVariableOfConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class LocalVariableOfConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
private LocalVariableOfConcreteClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitParameter(PsiParameter parameter) {
|
||||
super.visitParameter(parameter);
|
||||
|
||||
if (parameter.getParent() instanceof PsiTryStatement) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = parameter.getTypeElement();
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
final String variableName = parameter.getName();
|
||||
registerError(typeElement, variableName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiSuperMethodUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
|
||||
public class PublicMethodNotExposedInInterfaceInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Public method not exposed in interface";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
protected String buildErrorString(PsiElement location) {
|
||||
return "Public method '#ref' is not exposed via an interface #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new PublicMethodNotExposedInInterface(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class PublicMethodNotExposedInInterface extends BaseInspectionVisitor {
|
||||
private PublicMethodNotExposedInInterface(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
super.visitMethod(method);
|
||||
if (method.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return;
|
||||
}
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (containingClass.isInterface()|| containingClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return;
|
||||
}
|
||||
if (exposedInInterface(method)) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
private boolean exposedInInterface(PsiMethod method) {
|
||||
final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
|
||||
for (int i = 0; i < superMethods.length; i++) {
|
||||
final PsiMethod superMethod = superMethods[i];
|
||||
final PsiClass superClass = superMethod.getContainingClass();
|
||||
if (superClass.isInterface()) {
|
||||
return true;
|
||||
}
|
||||
final String superclassName = superClass.getQualifiedName();
|
||||
if ("java.lang.Object".equals(superclassName)) {
|
||||
return true;
|
||||
}
|
||||
if (exposedInInterface(superMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.VariableInspection;
|
||||
|
||||
public class RawUseOfParameterizedTypeInspection extends VariableInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Raw use of parameterized class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Raw use of parameterized class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new RawUseOfParameterizedTypeVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class RawUseOfParameterizedTypeVisitor extends BaseInspectionVisitor {
|
||||
private RawUseOfParameterizedTypeVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitVariable(PsiVariable variable) {
|
||||
super.visitVariable(variable);
|
||||
final PsiTypeElement typeElement = variable.getTypeElement();
|
||||
checkTypeElement(typeElement);
|
||||
}
|
||||
|
||||
public void visitTypeCastExpression(PsiTypeCastExpression cast) {
|
||||
super.visitTypeCastExpression(cast);
|
||||
final PsiTypeElement typeElement = cast.getCastType();
|
||||
checkTypeElement(typeElement);
|
||||
}
|
||||
|
||||
public void visitNewExpression(PsiNewExpression newExpression) {
|
||||
super.visitNewExpression(newExpression);
|
||||
final PsiJavaCodeReferenceElement classReference =
|
||||
newExpression.getClassReference();
|
||||
|
||||
if (classReference == null) {
|
||||
return;
|
||||
}
|
||||
final PsiElement referent = classReference.resolve();
|
||||
if (referent == null) {
|
||||
return;
|
||||
}
|
||||
if (!(referent instanceof PsiClass)) {
|
||||
return;
|
||||
}
|
||||
if (!((PsiClass) referent).hasTypeParameters()) {
|
||||
return;
|
||||
}
|
||||
if (newExpression.getTypeArgumentList() != null) {
|
||||
return;
|
||||
}
|
||||
registerError(classReference);
|
||||
}
|
||||
|
||||
private void checkTypeElement(PsiTypeElement typeElement) {
|
||||
if (typeElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = typeElement.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType componentType = type.getDeepComponentType();
|
||||
if (componentType == null) {
|
||||
return;
|
||||
}
|
||||
if (!(componentType instanceof PsiClassType)) {
|
||||
return;
|
||||
}
|
||||
final String typeText = componentType.getCanonicalText();
|
||||
if (typeText.indexOf((int) '<') >= 0) {
|
||||
return;
|
||||
}
|
||||
final PsiClass aClass = ((PsiClassType) componentType).resolve();
|
||||
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!aClass.hasTypeParameters()) {
|
||||
return;
|
||||
}
|
||||
final PsiElement typeNameElement =
|
||||
typeElement.getInnermostComponentReferenceElement();
|
||||
registerError(typeNameElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiTypeElement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.FieldInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class StaticVariableOfConcreteClassInspection extends FieldInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Concrete class for static variable";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(Object arg) {
|
||||
return "Static variable " + arg + " of concrete class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new StaticVariableOfConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class StaticVariableOfConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
private StaticVariableOfConcreteClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
super.visitField(field);
|
||||
if (!field.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
return;
|
||||
}
|
||||
final PsiTypeElement typeElement = field.getTypeElement();
|
||||
if (!ConcreteClassUtil.typeIsConcreteClass(typeElement)) {
|
||||
return;
|
||||
}
|
||||
final String variableName = field.getName();
|
||||
registerError(typeElement, variableName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.siyeh.ig.abstraction;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSwitchStatement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
public class SwitchStatementInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'switch' statement";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.ABSTRACTION_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'#ref' statement #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new SwitchStatementVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class SwitchStatementVisitor extends BaseInspectionVisitor {
|
||||
private SwitchStatementVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(PsiSwitchStatement statement) {
|
||||
super.visitSwitchStatement(statement);
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class AssignmentToNullInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Assignment to 'null'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Assignment of variable #ref to null #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AssignmentToNullVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AssignmentToNullVisitor extends BaseInspectionVisitor {
|
||||
private AssignmentToNullVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitLiteralExpression(PsiLiteralExpression value) {
|
||||
super.visitLiteralExpression(value);
|
||||
final String text = value.getText();
|
||||
if (!"null".equals(text)) {
|
||||
return;
|
||||
}
|
||||
PsiElement parent = value.getParent();
|
||||
while (parent != null &&
|
||||
(parent instanceof PsiParenthesizedExpression ||
|
||||
parent instanceof PsiConditionalExpression ||
|
||||
parent instanceof PsiTypeCastExpression)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent == null || !(parent instanceof PsiAssignmentExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = ((PsiAssignmentExpression) parent).getLExpression();
|
||||
registerError(lhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.siyeh.ig.*;
|
||||
|
||||
public class AssignmentUsedAsConditionInspection extends ExpressionInspection {
|
||||
private final AssignmentUsedAsConditionFix fix = new AssignmentUsedAsConditionFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Assignment used as condition";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref used as condition #loc";
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class AssignmentUsedAsConditionFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "replace '=' with '=='";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor problemDescriptor) {
|
||||
final PsiAssignmentExpression expression =
|
||||
(PsiAssignmentExpression) problemDescriptor.getPsiElement();
|
||||
final PsiExpression leftExpression = expression.getLExpression();
|
||||
final PsiExpression rightExpression = expression.getRExpression();
|
||||
final String newExpression = leftExpression.getText() + "==" + rightExpression.getText();
|
||||
replaceExpression(project, expression, newExpression);
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AssignmentUsedAsConditionVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AssignmentUsedAsConditionVisitor extends BaseInspectionVisitor {
|
||||
private AssignmentUsedAsConditionVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
if (sign.getTokenType() != JavaTokenType.EQ) {
|
||||
return;
|
||||
}
|
||||
final PsiElement parent = expression.getParent();
|
||||
if (parent instanceof PsiIfStatement) {
|
||||
checkIfStatementCondition((PsiIfStatement) parent, expression);
|
||||
}
|
||||
if (parent instanceof PsiWhileStatement) {
|
||||
checkWhileStatementCondition((PsiWhileStatement) parent, expression);
|
||||
}
|
||||
if (parent instanceof PsiForStatement) {
|
||||
checkForStatementCondition((PsiForStatement) parent, expression);
|
||||
}
|
||||
if (parent instanceof PsiDoWhileStatement) {
|
||||
checkDoWhileStatementCondition((PsiDoWhileStatement) parent, expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfStatementCondition(PsiIfStatement ifStatement, PsiAssignmentExpression expression) {
|
||||
final PsiExpression condition = ifStatement.getCondition();
|
||||
if (condition != null && condition.equals(expression)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDoWhileStatementCondition(PsiDoWhileStatement doWhileStatement, PsiAssignmentExpression expression) {
|
||||
final PsiExpression condition = doWhileStatement.getCondition();
|
||||
if (condition != null && condition.equals(expression)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForStatementCondition(PsiForStatement forStatement, PsiAssignmentExpression expression) {
|
||||
final PsiExpression condition = forStatement.getCondition();
|
||||
if (condition != null && condition.equals(expression)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkWhileStatementCondition(PsiWhileStatement whileStatement, PsiAssignmentExpression expression) {
|
||||
final PsiExpression condition = whileStatement.getCondition();
|
||||
if (condition != null && condition.equals(expression)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class CollectionQueryCalledVisitor extends PsiRecursiveElementVisitor {
|
||||
private static Set queryNames = new HashSet(10);
|
||||
|
||||
static {
|
||||
queryNames.add("get");
|
||||
queryNames.add("contains");
|
||||
queryNames.add("containsKey");
|
||||
queryNames.add("containsValue");
|
||||
queryNames.add("containsAll");
|
||||
queryNames.add("size");
|
||||
queryNames.add("indexOf");
|
||||
queryNames.add("iterator");
|
||||
queryNames.add("lastIndexOf");
|
||||
queryNames.add("toArray");
|
||||
queryNames.add("isEmpty");
|
||||
queryNames.add("entrySet");
|
||||
queryNames.add("keySet");
|
||||
queryNames.add("values");
|
||||
}
|
||||
|
||||
private boolean queried = false;
|
||||
private final PsiVariable variable;
|
||||
|
||||
public CollectionQueryCalledVisitor(PsiVariable variable) {
|
||||
super();
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression exp) {
|
||||
final PsiExpression qualifier = exp.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
qualifier.accept(this);
|
||||
}
|
||||
final PsiReferenceParameterList typeParameters = exp.getParameterList();
|
||||
if (typeParameters != null) {
|
||||
typeParameters.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitForeachStatement(PsiForeachStatement statement) {
|
||||
super.visitForeachStatement(statement);
|
||||
final PsiExpression qualifier = statement.getIteratedValue();
|
||||
if (qualifier == null) {
|
||||
return;
|
||||
}
|
||||
if (!(qualifier instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement referent = ((PsiReference) qualifier).resolve();
|
||||
if (referent == null) {
|
||||
return;
|
||||
}
|
||||
if (!referent.equals(variable)) {
|
||||
return;
|
||||
}
|
||||
queried = true;
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression call) {
|
||||
super.visitMethodCallExpression(call);
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
if (methodExpression == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
return;
|
||||
}
|
||||
if (!(qualifier instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement referent = ((PsiReference) qualifier).resolve();
|
||||
if (referent == null) {
|
||||
return;
|
||||
}
|
||||
if (!referent.equals(variable)) {
|
||||
return;
|
||||
}
|
||||
final boolean isStatement = call.getParent() instanceof PsiExpressionStatement;
|
||||
if (!isStatement) {
|
||||
queried = true;
|
||||
return;
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (queryNames.contains(methodName)) {
|
||||
queried = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isQueried() {
|
||||
return queried;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class CollectionUpdateCalledVisitor extends PsiRecursiveElementVisitor {
|
||||
private static Set updateNames = new HashSet(10);
|
||||
|
||||
static {
|
||||
updateNames.add("add");
|
||||
updateNames.add("put");
|
||||
updateNames.add("set");
|
||||
updateNames.add("remove");
|
||||
updateNames.add("addAll");
|
||||
updateNames.add("removeAll");
|
||||
updateNames.add("retainAll");
|
||||
updateNames.add("putAll");
|
||||
updateNames.add("clear");
|
||||
}
|
||||
|
||||
private boolean updated = false;
|
||||
private final PsiVariable variable;
|
||||
|
||||
public CollectionUpdateCalledVisitor(PsiVariable variable) {
|
||||
super();
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression exp) {
|
||||
final PsiExpression qualifier = exp.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
qualifier.accept(this);
|
||||
}
|
||||
final PsiReferenceParameterList typeParameters = exp.getParameterList();
|
||||
if (typeParameters != null) {
|
||||
typeParameters.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression call) {
|
||||
super.visitMethodCallExpression(call);
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
if (methodExpression == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
return;
|
||||
}
|
||||
if (!(qualifier instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement referent = ((PsiReference) qualifier).resolve();
|
||||
if (referent == null) {
|
||||
return;
|
||||
}
|
||||
if (!referent.equals(variable)) {
|
||||
return;
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (updateNames.contains(methodName)) {
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUpdated() {
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class CompareToUsesNonFinalVariableInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Non-final field referenced in 'compareTo()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Non-final field #ref accessed in compareTo() #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new CompareToUsesNonFinalVariableVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class CompareToUsesNonFinalVariableVisitor extends BaseInspectionVisitor {
|
||||
private boolean m_inCompareTo = false;
|
||||
|
||||
private CompareToUsesNonFinalVariableVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (!m_inCompareTo) {
|
||||
return;
|
||||
}
|
||||
final PsiElement element = expression.resolve();
|
||||
if (!(element instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
final PsiField field = (PsiField) element;
|
||||
if (field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
final boolean isCompareTo = isCompareTo(method);
|
||||
if (isCompareTo) {
|
||||
m_inCompareTo = true;
|
||||
}
|
||||
|
||||
super.visitMethod(method);
|
||||
if (isCompareTo) {
|
||||
m_inCompareTo = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCompareTo(PsiMethod method) {
|
||||
final String methodName = method.getName();
|
||||
if (!"compareTo".equals(methodName)) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
if (parameters == null || parameters.length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiType returnType = method.getReturnType();
|
||||
return TypeUtils.typeEquals("int", returnType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiBinaryExpression;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.ComparisonUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class ComparisonOfShortAndCharInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Comparison of short and char values";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Equality comparison (#ref) of short and char values #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ComparisonOfShortAndCharVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ComparisonOfShortAndCharVisitor extends BaseInspectionVisitor {
|
||||
private static final String SHORT = "short";
|
||||
private static final String CHAR = "char";
|
||||
|
||||
private ComparisonOfShortAndCharVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
if (!ComparisonUtils.isEqualityComparison(expression)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (TypeUtils.expressionHasType(SHORT, lhs) && TypeUtils.expressionHasType(CHAR, rhs)) {
|
||||
registerError(expression);
|
||||
} else if (TypeUtils.expressionHasType(CHAR, lhs) && TypeUtils.expressionHasType(SHORT, rhs)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class CovariantCompareToInspection extends MethodInspection {
|
||||
private static final String COMPARE_TO_METHOD_NAME = "compareTo";
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Covariant compareTo()";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref should take Object as it's argument #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new CovariantCompareToVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class CovariantCompareToVisitor extends BaseInspectionVisitor {
|
||||
|
||||
private CovariantCompareToVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
// note: no call to super
|
||||
final String name = method.getName();
|
||||
if (!COMPARE_TO_METHOD_NAME.equals(name)) {
|
||||
return;
|
||||
}
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList paramList = method.getParameterList();
|
||||
if (paramList == null) {
|
||||
return;
|
||||
}
|
||||
final PsiParameter[] parameters = paramList.getParameters();
|
||||
if (parameters.length != 1) {
|
||||
return;
|
||||
}
|
||||
final PsiType argType = parameters[0].getType();
|
||||
if (TypeUtils.isJavaLangObject(argType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (isNonVariantCompareTo(methods[i])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final PsiClassType[] implementsListTypes = aClass.getImplementsListTypes();
|
||||
for (int i = 0; i < implementsListTypes.length; i++) {
|
||||
final PsiClassType implementedType = implementsListTypes[i];
|
||||
final String implementedClassName = implementedType.getClassName();
|
||||
if (("java.lang.Comparable".equals(implementedClassName) ||
|
||||
"Comparable".equals(implementedClassName)
|
||||
)
|
||||
&& implementedType.hasParameters()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
private static boolean isNonVariantCompareTo(PsiMethod method) {
|
||||
final String methodName = method.getName();
|
||||
if (!COMPARE_TO_METHOD_NAME.equals(methodName)) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameterList paramList = method.getParameterList();
|
||||
if (paramList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameter[] parameters = paramList.getParameters();
|
||||
if (parameters.length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiType argType = parameters[0].getType();
|
||||
return TypeUtils.isJavaLangObject(argType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class CovariantEqualsInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Covariant equals()";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref should take Object as it's argument #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new CovariantEqualsVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class CovariantEqualsVisitor extends BaseInspectionVisitor {
|
||||
private static final String EQUALS_METHOD_NAME = "equals";
|
||||
|
||||
private CovariantEqualsVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
// note: no call to super
|
||||
final String name = method.getName();
|
||||
if (!EQUALS_METHOD_NAME.equals(name)) {
|
||||
return;
|
||||
}
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList paramList = method.getParameterList();
|
||||
if (paramList == null) {
|
||||
return;
|
||||
}
|
||||
final PsiParameter[] parameters = paramList.getParameters();
|
||||
if (parameters.length != 1) {
|
||||
return;
|
||||
}
|
||||
final PsiType argType = parameters[0].getType();
|
||||
if (TypeUtils.isJavaLangObject(argType)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (isNonVariantEquals(methods[i])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerMethodError(method);
|
||||
|
||||
}
|
||||
|
||||
private static boolean isNonVariantEquals(PsiMethod method) {
|
||||
final String name = method.getName();
|
||||
if (!EQUALS_METHOD_NAME.equals(name)) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameterList paramList = method.getParameterList();
|
||||
if (paramList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameter[] parameters = paramList.getParameters();
|
||||
if (parameters.length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiType argType = parameters[0].getType();
|
||||
return TypeUtils.isJavaLangObject(argType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
public class DefaultNotLastCaseInSwitchInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'default' not last case in 'switch'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'#ref' branch not last case in 'switch' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new DefaultNotLastCaseInSwitchVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class DefaultNotLastCaseInSwitchVisitor extends BaseInspectionVisitor {
|
||||
private DefaultNotLastCaseInSwitchVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(PsiSwitchStatement statement) {
|
||||
super.visitSwitchStatement(statement);
|
||||
final PsiCodeBlock body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
boolean labelSeen = false;
|
||||
for (int i = statements.length - 1; i >= 0; i--) {
|
||||
final PsiStatement child = statements[i];
|
||||
if (child instanceof PsiSwitchLabelStatement) {
|
||||
final PsiSwitchLabelStatement label = (PsiSwitchLabelStatement) child;
|
||||
if (label.isDefaultCase()) {
|
||||
if (labelSeen) {
|
||||
registerStatementError(label);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
labelSeen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClassInitializer;
|
||||
import com.intellij.psi.PsiCodeBlock;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiStatement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
public class EmptyInitializerInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Empty class initializer";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Empty class initializer #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new EmptyInitializerVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class EmptyInitializerVisitor extends BaseInspectionVisitor {
|
||||
private EmptyInitializerVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClassInitializer(PsiClassInitializer initializer) {
|
||||
super.visitClassInitializer(initializer);
|
||||
final PsiCodeBlock body = initializer.getBody();
|
||||
if (!codeBlockIsEmpty(body)) {
|
||||
return;
|
||||
}
|
||||
registerError(body.getLBrace());
|
||||
}
|
||||
|
||||
|
||||
private static boolean codeBlockIsEmpty(PsiCodeBlock codeBlock) {
|
||||
final PsiStatement[] statements = codeBlock.getStatements();
|
||||
return statements.length == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
import com.siyeh.ig.ui.SingleCheckboxOptionsPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class EmptyStatementBodyInspection extends StatementInspection {
|
||||
public boolean m_reportEmptyBlocks = false;
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Statement with empty body";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref statement has empty body #loc";
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel("Include statement bodies that are empty code blocks",
|
||||
this, "m_reportEmptyBlocks");
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new EmptyStatementVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private class EmptyStatementVisitor extends BaseInspectionVisitor {
|
||||
private EmptyStatementVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
|
||||
super.visitDoWhileStatement(statement);
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (!isEmpty(body)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitWhileStatement(PsiWhileStatement statement) {
|
||||
super.visitWhileStatement(statement);
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (!isEmpty(body)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitForStatement(PsiForStatement statement) {
|
||||
super.visitForStatement(statement);
|
||||
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (!isEmpty(body)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitForeachStatement(PsiForeachStatement statement) {
|
||||
super.visitForeachStatement(statement);
|
||||
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (!isEmpty(body)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitIfStatement(PsiIfStatement statement) {
|
||||
super.visitIfStatement(statement);
|
||||
final PsiStatement thenBranch = statement.getThenBranch();
|
||||
if (thenBranch != null) {
|
||||
if (isEmpty(thenBranch)) {
|
||||
registerStatementError(statement);
|
||||
return;
|
||||
}
|
||||
}
|
||||
final PsiStatement elseBranch = statement.getElseBranch();
|
||||
|
||||
if (elseBranch != null) {
|
||||
if (isEmpty(elseBranch)) {
|
||||
final PsiElement elseToken = statement.getElseElement();
|
||||
registerError(elseToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmpty(PsiElement body) {
|
||||
if (body instanceof PsiEmptyStatement) {
|
||||
return true;
|
||||
} else if (m_reportEmptyBlocks && body instanceof PsiBlockStatement) {
|
||||
final PsiBlockStatement block = (PsiBlockStatement) body;
|
||||
final PsiCodeBlock codeBlock = block.getCodeBlock();
|
||||
return codeBlockIsEmpty(codeBlock);
|
||||
} else if (body instanceof PsiCodeBlock) {
|
||||
final PsiCodeBlock codeBlock = (PsiCodeBlock) body;
|
||||
return codeBlockIsEmpty(codeBlock);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean codeBlockIsEmpty(PsiCodeBlock codeBlock) {
|
||||
final PsiStatement[] statements = codeBlock.getStatements();
|
||||
return statements.length == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class EqualsBetweenInconvertibleTypesInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "equals() between objects of inconvertible types";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final PsiReferenceExpression methodExpression = (PsiReferenceExpression) location.getParent();
|
||||
final PsiMethodCallExpression expression =
|
||||
(PsiMethodCallExpression) methodExpression.getParent();
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
final PsiType comparedType = args[0].getType();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
final PsiType comparisonType = qualifier.getType();
|
||||
|
||||
return "#ref() between objects of inconvertible types "
|
||||
+ comparisonType.getPresentableText() + " and "
|
||||
+ comparedType.getPresentableText() + " #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new EqualsBetweenInconvertibleTypesVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class EqualsBetweenInconvertibleTypesVisitor extends BaseInspectionVisitor {
|
||||
private EqualsBetweenInconvertibleTypesVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
if (methodExpression == null) {
|
||||
return;
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (!"equals".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
if (args == null) {
|
||||
return;
|
||||
}
|
||||
if (args.length != 1) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression arg = args[0];
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (!areIncompatibleTypes(arg, qualifier)) {
|
||||
return;
|
||||
}
|
||||
registerMethodCallError(expression);
|
||||
}
|
||||
|
||||
private static boolean areIncompatibleTypes(PsiExpression exp1, PsiExpression exp2) {
|
||||
if (exp1 == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType comparedType = exp1.getType();
|
||||
if (comparedType == null) {
|
||||
return false;
|
||||
}
|
||||
if (exp2 == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType comparisonType = exp2.getType();
|
||||
if (comparisonType == null) {
|
||||
return false;
|
||||
}
|
||||
if (TypeConversionUtil.areTypesConvertible(comparedType, comparisonType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class EqualsUsesNonFinalVariableInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Non-final field referenced in 'equals()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Non-final field #ref accessed in equals() #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new EqualsUsesNonFinalVariableVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class EqualsUsesNonFinalVariableVisitor extends BaseInspectionVisitor {
|
||||
private boolean m_inEquals = false;
|
||||
|
||||
private EqualsUsesNonFinalVariableVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (!m_inEquals) {
|
||||
return;
|
||||
}
|
||||
final PsiElement element = expression.resolve();
|
||||
if (!(element instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
final PsiField field = (PsiField) element;
|
||||
if (field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
final boolean isEquals = isEqualsMethod(method);
|
||||
if (isEquals) {
|
||||
m_inEquals = true;
|
||||
}
|
||||
|
||||
super.visitMethod(method);
|
||||
if (isEquals) {
|
||||
m_inEquals = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isEqualsMethod(PsiMethod method) {
|
||||
final String methodName = method.getName();
|
||||
if (!"equals".equals(methodName)) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
if (parameters == null || parameters.length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (returnType == null) {
|
||||
return false;
|
||||
}
|
||||
if (!returnType.equals(PsiType.BOOLEAN)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
import com.siyeh.ig.psiutils.ControlFlowUtils;
|
||||
|
||||
public class FallthruInSwitchStatementInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Fallthrough in 'switch' statement";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref fallthrough in 'switch' statement #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FallthroughInSwitchStatementVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class FallthroughInSwitchStatementVisitor extends BaseInspectionVisitor {
|
||||
private FallthroughInSwitchStatementVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(PsiSwitchStatement statement) {
|
||||
super.visitSwitchStatement(statement);
|
||||
boolean switchLabelValid = true;
|
||||
final PsiCodeBlock body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
final PsiStatement child = statements[i];
|
||||
if (child instanceof PsiSwitchLabelStatement) {
|
||||
if (!switchLabelValid) {
|
||||
registerError(child);
|
||||
}
|
||||
switchLabelValid = true;
|
||||
} else {
|
||||
switchLabelValid = !ControlFlowUtils.statementMayCompleteNormally(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class FloatingPointEqualityInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Floating point equality comparison";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref: floating point values compared for exact equality #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FloatingPointEqualityComparisonVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class FloatingPointEqualityComparisonVisitor extends BaseInspectionVisitor {
|
||||
private FloatingPointEqualityComparisonVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!(tokenType.equals(JavaTokenType.EQEQ) ||
|
||||
tokenType.equals(JavaTokenType.NE))) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
if (isFloatingPointType(lhs)) {
|
||||
registerError(expression);
|
||||
return;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (isFloatingPointType(rhs)) {
|
||||
registerError(expression);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isFloatingPointType(PsiExpression expression) {
|
||||
if(expression == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final PsiType type = expression.getType();
|
||||
return TypeConversionUtil.isDoubleType(type) ||
|
||||
TypeConversionUtil.isFloatType(type);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ForLoopThatDoesntUseLoopVariableInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "For loop where update or condition doesn't use loop variable";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final List compenentsMissing = new ArrayList(3);
|
||||
final PsiJavaToken forToken = (PsiJavaToken) location;
|
||||
final PsiForStatement forStatement = (PsiForStatement) forToken.getParent();
|
||||
|
||||
if (!conditionUsesInitializer(forStatement)) {
|
||||
compenentsMissing.add("condition");
|
||||
}
|
||||
if (!updateUsesInitializer(forStatement)) {
|
||||
compenentsMissing.add("update");
|
||||
}
|
||||
final String missingComponents;
|
||||
final String doString;
|
||||
if (compenentsMissing.size() == 1) {
|
||||
missingComponents = (String) compenentsMissing.get(0);
|
||||
doString = "does";
|
||||
} else {
|
||||
missingComponents = compenentsMissing.get(0) + " and " + compenentsMissing.get(1);
|
||||
doString = "do";
|
||||
}
|
||||
return "#ref statement has " + missingComponents + " which " + doString + " not use the for loop variable #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ForLoopThatDoesntUseLoopVariableVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ForLoopThatDoesntUseLoopVariableVisitor extends BaseInspectionVisitor {
|
||||
private ForLoopThatDoesntUseLoopVariableVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitForStatement(PsiForStatement statement) {
|
||||
super.visitForStatement(statement);
|
||||
|
||||
if (conditionUsesInitializer(statement)
|
||||
&& updateUsesInitializer(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean conditionUsesInitializer(PsiForStatement statement) {
|
||||
final PsiStatement initialization = statement.getInitialization();
|
||||
final PsiExpression condition = statement.getCondition();
|
||||
|
||||
if (initialization == null) {
|
||||
return true;
|
||||
}
|
||||
if (condition == null) {
|
||||
return true;
|
||||
}
|
||||
if (!(initialization instanceof PsiDeclarationStatement)) {
|
||||
return true;
|
||||
}
|
||||
final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization;
|
||||
|
||||
final PsiElement[] declaredElements = declaration.getDeclaredElements();
|
||||
|
||||
if (declaredElements == null || declaredElements.length != 1) {
|
||||
return true;
|
||||
}
|
||||
if (declaredElements[0] == null || !(declaredElements[0] instanceof PsiLocalVariable)) {
|
||||
return true;
|
||||
}
|
||||
final PsiLocalVariable localVar = (PsiLocalVariable) declaredElements[0];
|
||||
return expressionUsesVariable(condition, localVar);
|
||||
}
|
||||
|
||||
private static boolean updateUsesInitializer(PsiForStatement statement) {
|
||||
final PsiStatement initialization = statement.getInitialization();
|
||||
final PsiStatement update = statement.getUpdate();
|
||||
|
||||
if (initialization == null) {
|
||||
return true;
|
||||
}
|
||||
if (update == null) {
|
||||
return true;
|
||||
}
|
||||
if (!(initialization instanceof PsiDeclarationStatement)) {
|
||||
return true;
|
||||
}
|
||||
final PsiDeclarationStatement declaration = (PsiDeclarationStatement) initialization;
|
||||
|
||||
final PsiElement[] declaredElements = declaration.getDeclaredElements();
|
||||
|
||||
if (declaredElements == null || declaredElements.length != 1) {
|
||||
return true;
|
||||
}
|
||||
if (declaredElements[0] == null || !(declaredElements[0] instanceof PsiLocalVariable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiLocalVariable localVar = (PsiLocalVariable) declaredElements[0];
|
||||
return statementUsesVariable(update, localVar);
|
||||
}
|
||||
|
||||
private static boolean statementUsesVariable(PsiStatement statement, PsiLocalVariable localVar) {
|
||||
final UseVisitor useVisitor = new UseVisitor(localVar);
|
||||
statement.accept(useVisitor);
|
||||
return useVisitor.isUsed();
|
||||
}
|
||||
|
||||
private static boolean expressionUsesVariable(PsiExpression expression, PsiLocalVariable localVar) {
|
||||
final UseVisitor useVisitor = new UseVisitor(localVar);
|
||||
expression.accept(useVisitor);
|
||||
return useVisitor.isUsed();
|
||||
}
|
||||
|
||||
private static class UseVisitor extends PsiRecursiveElementVisitor {
|
||||
private final PsiLocalVariable m_variable;
|
||||
private boolean m_used = false;
|
||||
|
||||
private UseVisitor(PsiLocalVariable var) {
|
||||
super();
|
||||
m_variable = var;
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression ref) {
|
||||
final PsiExpression qualifier = ref.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
qualifier.accept(this);
|
||||
}
|
||||
final PsiReferenceParameterList typeParameters = ref.getParameterList();
|
||||
if (typeParameters != null) {
|
||||
typeParameters.accept(this);
|
||||
}
|
||||
final PsiElement resolvedElement = ref.resolve();
|
||||
if (m_variable.equals(resolvedElement)) {
|
||||
m_used = true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUsed() {
|
||||
return m_used;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ForLoopWithMissingComponentInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "For loop with missing components";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final List components = new ArrayList(3);
|
||||
final PsiJavaToken forToken = (PsiJavaToken) location;
|
||||
final PsiForStatement forStatement = (PsiForStatement) forToken.getParent();
|
||||
|
||||
if (!hasInitializer(forStatement)) {
|
||||
components.add("initializer");
|
||||
}
|
||||
if (!hasCondition(forStatement)) {
|
||||
components.add("condition");
|
||||
}
|
||||
if (!hasUpdate(forStatement)) {
|
||||
components.add("update");
|
||||
}
|
||||
final String missingComponents;
|
||||
if (components.size() == 1) {
|
||||
missingComponents = (String) components.get(0);
|
||||
} else if (components.size() == 2) {
|
||||
missingComponents = components.get(0) + " and " + components.get(1);
|
||||
} else {
|
||||
missingComponents = components.get(0) + ", " + components.get(1) + " and " + components.get(2);
|
||||
}
|
||||
return "#ref statement lacks " + missingComponents + " #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ForLoopWithMissingComponentVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ForLoopWithMissingComponentVisitor extends BaseInspectionVisitor {
|
||||
private ForLoopWithMissingComponentVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitForStatement(PsiForStatement statement) {
|
||||
super.visitForStatement(statement);
|
||||
|
||||
if (hasCondition(statement)
|
||||
&& hasInitializer(statement)
|
||||
&& hasUpdate(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCondition(PsiForStatement statement) {
|
||||
return statement.getCondition() != null;
|
||||
}
|
||||
|
||||
private static boolean hasInitializer(PsiForStatement statement) {
|
||||
final PsiStatement initialization = statement.getInitialization();
|
||||
return initialization != null && !(initialization instanceof PsiEmptyStatement);
|
||||
}
|
||||
|
||||
private static boolean hasUpdate(PsiForStatement statement) {
|
||||
final PsiStatement update = statement.getUpdate();
|
||||
return update != null && !(update instanceof PsiEmptyStatement);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class HashCodeUsesNonFinalVariableInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Non-final field referenced in 'hashCode()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Non-final field #ref accessed in hashCode() #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new HashCodeUsesNonFinalVariableVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class HashCodeUsesNonFinalVariableVisitor extends BaseInspectionVisitor {
|
||||
private boolean m_inHashcode = false;
|
||||
|
||||
private HashCodeUsesNonFinalVariableVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (!m_inHashcode) {
|
||||
return;
|
||||
}
|
||||
final PsiElement element = expression.resolve();
|
||||
if (!(element instanceof PsiField)) {
|
||||
return;
|
||||
}
|
||||
final PsiField field = (PsiField) element;
|
||||
if (field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
final boolean isHashCode = isHashCode(method);
|
||||
if (isHashCode) {
|
||||
m_inHashcode = true;
|
||||
}
|
||||
|
||||
super.visitMethod(method);
|
||||
if (isHashCode) {
|
||||
m_inHashcode = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isHashCode(PsiMethod method) {
|
||||
final String methodName = method.getName();
|
||||
if (!"hashCode".equals(methodName)) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
if (parameters == null || parameters.length != 0) {
|
||||
return false;
|
||||
}
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (returnType == null) {
|
||||
return false;
|
||||
}
|
||||
if (!returnType.equals(PsiType.INT)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.siyeh.ig.bugs.IgnoreResultOfCallInspection.Form">
|
||||
<grid id="9993d" binding="contentPanel" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="92" y="33" width="211" height="192"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<scrollpane id="14807">
|
||||
<constraints>
|
||||
<xy x="0" y="0" width="211" height="163"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="b0978" class="javax.swing.JTable" binding="table">
|
||||
<constraints/>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
<component id="f6174" class="javax.swing.JButton" binding="deleteButton">
|
||||
<constraints>
|
||||
<xy x="105" y="168" width="106" height="24"/>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Delete"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="52926" class="javax.swing.JButton" binding="addButton">
|
||||
<constraints>
|
||||
<xy x="0" y="168" width="95" height="24"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Add"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,241 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import org.jdom.Element;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EtchedBorder;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class IgnoreResultOfCallInspection extends ExpressionInspection {
|
||||
public String callCheckString = "java.io.InputStream,read," +
|
||||
"java.io.InputStream,skip," +
|
||||
"java.lang.StringBuffer,toString," +
|
||||
"java.lang.StringBuilder,toString," +
|
||||
"java.lang.String,.*," +
|
||||
"java.math.BigInteger,.*," +
|
||||
"java.math.BigDecimal,.*," +
|
||||
"java.net.InetAddress,.*";
|
||||
|
||||
private List callsToCheck = new ArrayList(32);
|
||||
|
||||
{
|
||||
parseCallCheckString();
|
||||
}
|
||||
|
||||
public void readSettings(Element element) throws InvalidDataException {
|
||||
super.readSettings(element);
|
||||
parseCallCheckString();
|
||||
}
|
||||
|
||||
private void parseCallCheckString() {
|
||||
callsToCheck.clear();
|
||||
final String[] strings = callCheckString.split(",");
|
||||
for (int i = 0; i < strings.length; i += 2) {
|
||||
final String className = strings[i];
|
||||
final String methodName = strings[i + 1];
|
||||
callsToCheck.add(new ReturnCheckSpecification(className, methodName));
|
||||
}
|
||||
}
|
||||
|
||||
public void writeSettings(Element element) throws WriteExternalException {
|
||||
formatCallCheckString();
|
||||
super.writeSettings(element);
|
||||
}
|
||||
|
||||
private void formatCallCheckString() {
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
boolean first = true;
|
||||
for (Iterator iterator = callsToCheck.iterator(); iterator.hasNext();) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
buffer.append(',');
|
||||
}
|
||||
final ReturnCheckSpecification returnCheckSpecification =
|
||||
(ReturnCheckSpecification) iterator.next();
|
||||
final String methodName = returnCheckSpecification.getMethodName();
|
||||
final String className = returnCheckSpecification.getClassName();
|
||||
buffer.append(className);
|
||||
buffer.append(',');
|
||||
buffer.append(methodName);
|
||||
}
|
||||
callCheckString = buffer.toString();
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Result of method call ignored";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
final Form form = new Form();
|
||||
return form.getContentPanel();
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final PsiElement parent = location.getParent();
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) parent.getParent();
|
||||
final PsiMethod method = methodCallExpression.resolveMethod();
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
final String className = containingClass.getName();
|
||||
return "result of " + className + ".#ref() is ignored. #loc ";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new IgnoreResultOfCallVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private class IgnoreResultOfCallVisitor extends BaseInspectionVisitor {
|
||||
private IgnoreResultOfCallVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitExpressionStatement(PsiExpressionStatement statement) {
|
||||
super.visitExpressionStatement(statement);
|
||||
if (!(statement.getExpression() instanceof PsiMethodCallExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethodCallExpression call = (PsiMethodCallExpression) statement.getExpression();
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (methodName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiMethod method = call.resolveMethod();
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Iterator iterator = callsToCheck.iterator(); iterator.hasNext();) {
|
||||
final ReturnCheckSpecification spec = (ReturnCheckSpecification) iterator.next();
|
||||
final Pattern methodNamePattern = spec.getMethodNamePattern();
|
||||
if (methodNamePattern != null &&
|
||||
methodNamesMatch(methodName, methodNamePattern)) {
|
||||
final String classNameToCompare = spec.getClassName();
|
||||
if (ClassUtils.isSubclass(aClass, classNameToCompare)) {
|
||||
registerMethodCallError(call);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean methodNamesMatch(String methodName, Pattern methodNamePattern) {
|
||||
final Matcher matcher = methodNamePattern.matcher(methodName);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Form {
|
||||
private JPanel contentPanel;
|
||||
private JButton addButton;
|
||||
private JButton deleteButton;
|
||||
private JTable table;
|
||||
|
||||
public Form() {
|
||||
super();
|
||||
table.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
|
||||
table.setRowSelectionAllowed(true);
|
||||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
table.setEnabled(true);
|
||||
final ReturnCheckSpecificationTableModel model =
|
||||
new ReturnCheckSpecificationTableModel();
|
||||
table.setModel(model);
|
||||
addButton.setEnabled(true);
|
||||
addButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
callsToCheck.add(new ReturnCheckSpecification());
|
||||
model.fireTableStructureChanged();
|
||||
}
|
||||
});
|
||||
deleteButton.setEnabled(true);
|
||||
deleteButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final int[] selectedRows = table.getSelectedRows();
|
||||
Arrays.sort(selectedRows);
|
||||
for (int i = selectedRows.length - 1; i >= 0; i--) {
|
||||
callsToCheck.remove(selectedRows[i]);
|
||||
}
|
||||
model.fireTableStructureChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public JComponent getContentPanel() {
|
||||
return contentPanel;
|
||||
}
|
||||
}
|
||||
|
||||
private class ReturnCheckSpecificationTableModel extends AbstractTableModel {
|
||||
|
||||
public int getRowCount() {
|
||||
return callsToCheck.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String getColumnName(int columnIndex) {
|
||||
if (columnIndex == 0) {
|
||||
return "Class name";
|
||||
}
|
||||
return "Method name";
|
||||
}
|
||||
|
||||
public Class getColumnClass(int columnIndex) {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
final ReturnCheckSpecification spec = (ReturnCheckSpecification) callsToCheck.get(rowIndex);
|
||||
if (columnIndex == 0) {
|
||||
return spec.getClassName();
|
||||
} else {
|
||||
return spec.getMethodName();
|
||||
}
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
final ReturnCheckSpecification spec = (ReturnCheckSpecification) callsToCheck.get(rowIndex);
|
||||
if (columnIndex == 0) {
|
||||
spec.setClassName((String) aValue);
|
||||
} else {
|
||||
spec.setMethodName((String) aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.ConstantExpressionUtil;
|
||||
import com.intellij.psi.util.IsConstantExpressionVisitor;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class IncompatibleMaskInspection extends ExpressionInspection {
|
||||
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Incompatible bitwise mask operation";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) location;
|
||||
final PsiJavaToken operationSign = binaryExpression.getOperationSign();
|
||||
final IElementType tokenType = operationSign.getTokenType();
|
||||
if (tokenType.equals(JavaTokenType.EQEQ)) {
|
||||
return "#ref is always false #loc";
|
||||
} else {
|
||||
return "#ref is always true #loc";
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new IncompatibleMaskVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
|
||||
private static class IncompatibleMaskVisitor extends BaseInspectionVisitor {
|
||||
private IncompatibleMaskVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
final PsiType expressionType = expression.getType();
|
||||
if (expressionType == null) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.EQEQ) && !tokenType.equals(JavaTokenType.NE)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
final PsiExpression strippedRhs = stripExpression(rhs);
|
||||
if (strippedRhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
final PsiExpression strippedLhs = stripExpression(lhs);
|
||||
if (strippedLhs == null) {
|
||||
return;
|
||||
}
|
||||
if (isConstantMask(strippedLhs) && isConstant(strippedRhs)) {
|
||||
if (isIncompatibleMask((PsiBinaryExpression) strippedLhs, strippedRhs)) {
|
||||
registerError(expression);
|
||||
}
|
||||
} else if (isConstantMask(strippedRhs) && isConstant(strippedLhs)) {
|
||||
if (isIncompatibleMask((PsiBinaryExpression) strippedRhs, strippedLhs)) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static PsiExpression stripExpression(PsiExpression exp) {
|
||||
if (exp == null) {
|
||||
return null;
|
||||
}
|
||||
if (exp instanceof PsiParenthesizedExpression) {
|
||||
final PsiExpression body =
|
||||
((PsiParenthesizedExpression) exp).getExpression();
|
||||
return stripExpression(body);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
private static boolean isIncompatibleMask(PsiBinaryExpression maskExpression, PsiExpression constantExpression) {
|
||||
final PsiJavaToken sign = maskExpression.getOperationSign();
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
final Object constantValue =
|
||||
ConstantExpressionUtil.computeCastTo(constantExpression, PsiType.LONG);
|
||||
if (constantValue == null) {
|
||||
return false;
|
||||
}
|
||||
final long constantLongValue = ((Long) constantValue).longValue();
|
||||
|
||||
final long constantMaskValue;
|
||||
final PsiExpression maskRhs = maskExpression.getROperand();
|
||||
final PsiExpression maskLhs = maskExpression.getLOperand();
|
||||
if (isConstant(maskRhs)) {
|
||||
final Object rhsValue =
|
||||
ConstantExpressionUtil.computeCastTo(maskRhs, PsiType.LONG);
|
||||
constantMaskValue = ((Long) rhsValue).longValue();
|
||||
} else {
|
||||
final Object lhsValue =
|
||||
ConstantExpressionUtil.computeCastTo(maskLhs, PsiType.LONG);
|
||||
constantMaskValue = ((Long) lhsValue).longValue();
|
||||
}
|
||||
|
||||
if (tokenType.equals(JavaTokenType.OR)) {
|
||||
if ((constantMaskValue | constantLongValue) != constantLongValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (tokenType.equals(JavaTokenType.AND)) {
|
||||
if ((constantMaskValue | constantLongValue) != constantMaskValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isConstant(PsiExpression expression) {
|
||||
if (expression == null) {
|
||||
return false;
|
||||
}
|
||||
final IsConstantExpressionVisitor visitor =
|
||||
new IsConstantExpressionVisitor();
|
||||
expression.accept(visitor);
|
||||
if (!visitor.isConstant()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isConstantMask(PsiExpression expression) {
|
||||
if (expression == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(expression instanceof PsiBinaryExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) expression;
|
||||
final PsiJavaToken sign = binaryExpression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return false;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.OR) && !tokenType.equals(JavaTokenType.AND)) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression rhs = binaryExpression.getROperand();
|
||||
if (isConstant(rhs)) {
|
||||
return true;
|
||||
}
|
||||
final PsiExpression lhs = binaryExpression.getLOperand();
|
||||
if (isConstant(lhs)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiDoWhileStatement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiForStatement;
|
||||
import com.intellij.psi.PsiWhileStatement;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
import com.siyeh.ig.psiutils.ControlFlowUtils;
|
||||
|
||||
public class InfiniteLoopStatementInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Infinite loop statement";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref statement cannot complete without throwing an exception #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InfiniteLoopStatementsVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InfiniteLoopStatementsVisitor extends BaseInspectionVisitor {
|
||||
private InfiniteLoopStatementsVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitForStatement(PsiForStatement statement) {
|
||||
super.visitForStatement(statement);
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(statement)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementContainsReturn(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitWhileStatement(PsiWhileStatement statement) {
|
||||
|
||||
super.visitWhileStatement(statement);
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(statement)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementContainsReturn(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
|
||||
super.visitDoWhileStatement(statement);
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(statement)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementContainsReturn(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
import com.siyeh.ig.psiutils.RecursionUtils;
|
||||
|
||||
public class InfiniteRecursionInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Infinite recursion";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Method #ref recurses infinitely, and can only end by throw an exception #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InfiniteRecursionVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InfiniteRecursionVisitor extends BaseInspectionVisitor {
|
||||
private InfiniteRecursionVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
super.visitMethod(method);
|
||||
if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
if (!RecursionUtils.methodMayRecurse(method)) {
|
||||
return;
|
||||
}
|
||||
if (!RecursionUtils.methodMustRecurseBeforeReturning(method)) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class IntegerDivisionInFloatingPointContextInspection extends ExpressionInspection {
|
||||
private static final Set s_integralTypes = new HashSet(10);
|
||||
|
||||
static {
|
||||
s_integralTypes.add("int");
|
||||
s_integralTypes.add("long");
|
||||
s_integralTypes.add("short");
|
||||
s_integralTypes.add("byte");
|
||||
s_integralTypes.add("char");
|
||||
s_integralTypes.add("java.lang.Integer");
|
||||
s_integralTypes.add("java.lang.Long");
|
||||
s_integralTypes.add("java.lang.Short");
|
||||
s_integralTypes.add("java.lang.Byte");
|
||||
s_integralTypes.add("java.lang.Char");
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Integer division in floating point context";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref: integer division in floating-point context #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FloatingPointEqualityComparisonVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class FloatingPointEqualityComparisonVisitor extends BaseInspectionVisitor {
|
||||
|
||||
private FloatingPointEqualityComparisonVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.DIV)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
if (lhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType lhsType = lhs.getType();
|
||||
if (!isIntegral(lhsType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType rhsType = rhs.getType();
|
||||
if (!isIntegral(rhsType)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression context = getContainingExpression(expression);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType contextType = ExpectedTypeUtils.findExpectedType(context);
|
||||
if (contextType == null) {
|
||||
return;
|
||||
}
|
||||
if (!(contextType.equals(PsiType.FLOAT)
|
||||
|| contextType.equals(PsiType.DOUBLE))) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
|
||||
private PsiExpression getContainingExpression(PsiExpression expression) {
|
||||
final PsiElement parent = expression.getParent();
|
||||
if (parent == null) {
|
||||
return expression;
|
||||
}
|
||||
if (parent instanceof PsiPrefixExpression ||
|
||||
parent instanceof PsiPostfixExpression ||
|
||||
parent instanceof PsiBinaryExpression ||
|
||||
parent instanceof PsiParenthesizedExpression) {
|
||||
return getContainingExpression((PsiExpression) parent);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isIntegral(PsiType type) {
|
||||
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
final String text = type.getCanonicalText();
|
||||
if (text == null) {
|
||||
return false;
|
||||
}
|
||||
return s_integralTypes.contains(text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
import com.siyeh.ig.psiutils.ControlFlowUtils;
|
||||
|
||||
public class LoopStatementsThatDontLoopInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Loop statement that doesn't loop";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref statement doesn't loop #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new LoopStatementsThatDontLoopVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class LoopStatementsThatDontLoopVisitor extends BaseInspectionVisitor {
|
||||
private LoopStatementsThatDontLoopVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitForStatement(PsiForStatement statement) {
|
||||
super.visitForStatement(statement);
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(body)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementIsContinueTarget(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitForeachStatement(PsiForeachStatement statement) {
|
||||
super.visitForeachStatement(statement);
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(body)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementIsContinueTarget(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitWhileStatement(PsiWhileStatement statement) {
|
||||
super.visitWhileStatement(statement);
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(body)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementIsContinueTarget(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
|
||||
super.visitDoWhileStatement(statement);
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementMayCompleteNormally(body)) {
|
||||
return;
|
||||
}
|
||||
if (ControlFlowUtils.statementIsContinueTarget(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.psiutils.*;
|
||||
|
||||
public class MismatchedArrayReadWriteInspection extends VariableInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Mismatched read and write of array";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final PsiVariable variable = (PsiVariable) location.getParent();
|
||||
final PsiElement context;
|
||||
if (variable instanceof PsiField) {
|
||||
context = ((PsiMember) variable).getContainingClass();
|
||||
} else {
|
||||
context = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
|
||||
}
|
||||
final boolean written = arrayContentsAreWritten(variable, context);
|
||||
final boolean read = arrayContentsAreRead(variable, context);
|
||||
if (written) {
|
||||
return "Contents of array #ref are written to, but never read #loc";
|
||||
} else if (read) {
|
||||
return "Contents of array #ref are read, but never written to #loc";
|
||||
} else {
|
||||
return "Contents of array #ref are neither read nor written to #loc";
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MismatchedArrayReadWriteVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MismatchedArrayReadWriteVisitor extends BaseInspectionVisitor {
|
||||
private MismatchedArrayReadWriteVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
super.visitField(field);
|
||||
if (!field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = field.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = field.getType();
|
||||
if (type.getArrayDimensions() == 0) {
|
||||
return;
|
||||
}
|
||||
final boolean written = arrayContentsAreWritten(field, containingClass);
|
||||
final boolean read = arrayContentsAreRead(field, containingClass);
|
||||
if (written && read) {
|
||||
return;
|
||||
}
|
||||
registerFieldError(field);
|
||||
}
|
||||
|
||||
|
||||
public void visitLocalVariable(PsiLocalVariable variable) {
|
||||
super.visitLocalVariable(variable);
|
||||
final PsiCodeBlock codeBlock =
|
||||
(PsiCodeBlock) PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
|
||||
if (codeBlock == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = variable.getType();
|
||||
if (type.getArrayDimensions() == 0) {
|
||||
return;
|
||||
}
|
||||
final boolean written = arrayContentsAreWritten(variable, codeBlock);
|
||||
final boolean read = arrayContentsAreRead(variable, codeBlock);
|
||||
if (written && read) {
|
||||
return;
|
||||
}
|
||||
registerVariableError(variable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static boolean arrayContentsAreWritten(PsiVariable variable, PsiElement context) {
|
||||
final PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null && !isDefaultArrayInitializer(initializer)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsAssigned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsAssignedFrom(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.arrayContentsAreAssigned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isDefaultArrayInitializer(PsiExpression initializer) {
|
||||
if (!(initializer instanceof PsiNewExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiNewExpression newExpression = (PsiNewExpression) initializer;
|
||||
if (newExpression.getArrayInitializer() != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean arrayContentsAreRead(PsiVariable variable, PsiElement context) {
|
||||
final PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null && !isDefaultArrayInitializer(initializer)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsAssigned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsAssignedFrom(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsReturned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (VariableAccessUtils.arrayContentsAreAccessed(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.psiutils.CollectionUtils;
|
||||
import com.siyeh.ig.psiutils.VariableAssignedFromVisitor;
|
||||
import com.siyeh.ig.psiutils.VariablePassedAsArgumentVisitor;
|
||||
import com.siyeh.ig.psiutils.VariableReturnedVisitor;
|
||||
|
||||
public class MismatchedCollectionQueryUpdateInspection extends VariableInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Mismatched query and update of collection";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final PsiVariable variable = (PsiVariable) location.getParent();
|
||||
final PsiElement context;
|
||||
if (variable instanceof PsiField) {
|
||||
context = ((PsiMember) variable).getContainingClass();
|
||||
} else {
|
||||
context = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
|
||||
}
|
||||
final boolean updated = collectionContentsAreUpdated(variable, context);
|
||||
final boolean queried = collectionContentsAreQueried(variable, context);
|
||||
if (updated) {
|
||||
return "Contents of collection #ref are updated, but never queried #loc";
|
||||
} else if (queried) {
|
||||
return "Contents of collection #ref are queried, but never updated #loc";
|
||||
} else {
|
||||
return "Contents of collection #ref are neither queried nor updated #loc";
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MismatchedCollectionQueryUpdateVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MismatchedCollectionQueryUpdateVisitor extends BaseInspectionVisitor {
|
||||
private MismatchedCollectionQueryUpdateVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
super.visitField(field);
|
||||
if (!field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = field.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = field.getType();
|
||||
if (!CollectionUtils.isCollectionClassOrInterface(type)) {
|
||||
return;
|
||||
}
|
||||
final boolean written = collectionContentsAreUpdated(field, containingClass);
|
||||
final boolean read = collectionContentsAreQueried(field, containingClass);
|
||||
if (written && read) {
|
||||
return;
|
||||
}
|
||||
registerFieldError(field);
|
||||
}
|
||||
|
||||
|
||||
public void visitLocalVariable(PsiLocalVariable variable) {
|
||||
super.visitLocalVariable(variable);
|
||||
|
||||
final PsiCodeBlock codeBlock =
|
||||
(PsiCodeBlock) PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
|
||||
if (codeBlock == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = variable.getType();
|
||||
if (!CollectionUtils.isCollectionClassOrInterface(type)) {
|
||||
return;
|
||||
}
|
||||
final boolean written = collectionContentsAreUpdated(variable, codeBlock);
|
||||
final boolean read = collectionContentsAreQueried(variable, codeBlock);
|
||||
if (written && read) {
|
||||
return;
|
||||
}
|
||||
registerVariableError(variable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static boolean collectionContentsAreUpdated(PsiVariable variable, PsiElement context) {
|
||||
final PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null && !isEmptyCollectionInitializer(initializer)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsAssigned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsAssignedFrom(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsPassedAsMethodArgument(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (collectionUpdateCalled(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean collectionContentsAreQueried(PsiVariable variable, PsiElement context) {
|
||||
final PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null && !isEmptyCollectionInitializer(initializer)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsAssigned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsAssignedFrom(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsReturned(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (variableIsPassedAsMethodArgument(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
if (collectionQueryCalled(variable, context)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean variableIsAssignedFrom(PsiVariable variable, PsiElement context) {
|
||||
final VariableAssignedFromVisitor visitor = new VariableAssignedFromVisitor(variable);
|
||||
context.accept(visitor);
|
||||
return visitor.isAssignedFrom();
|
||||
}
|
||||
|
||||
private static boolean variableIsPassedAsMethodArgument(PsiVariable variable, PsiElement context) {
|
||||
final VariablePassedAsArgumentVisitor visitor = new VariablePassedAsArgumentVisitor(variable);
|
||||
context.accept(visitor);
|
||||
return visitor.isPassed();
|
||||
}
|
||||
|
||||
private static boolean variableIsAssigned(PsiVariable variable, PsiElement context) {
|
||||
final VariableAssignedFromVisitor visitor = new VariableAssignedFromVisitor(variable);
|
||||
context.accept(visitor);
|
||||
return visitor.isAssignedFrom();
|
||||
}
|
||||
|
||||
|
||||
private static boolean variableIsReturned(PsiVariable variable, PsiElement context) {
|
||||
final VariableReturnedVisitor visitor = new VariableReturnedVisitor(variable);
|
||||
context.accept(visitor);
|
||||
return visitor.isReturned();
|
||||
}
|
||||
|
||||
private static boolean collectionQueryCalled(PsiVariable variable, PsiElement context) {
|
||||
final CollectionQueryCalledVisitor visitor = new CollectionQueryCalledVisitor(variable);
|
||||
context.accept(visitor);
|
||||
return visitor.isQueried();
|
||||
}
|
||||
|
||||
private static boolean collectionUpdateCalled(PsiVariable variable, PsiElement context) {
|
||||
final CollectionUpdateCalledVisitor visitor = new CollectionUpdateCalledVisitor(variable);
|
||||
context.accept(visitor);
|
||||
return visitor.isUpdated();
|
||||
}
|
||||
|
||||
private static boolean isEmptyCollectionInitializer(PsiExpression initializer) {
|
||||
if (!(initializer instanceof PsiNewExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiNewExpression newExpression = (PsiNewExpression) initializer;
|
||||
final PsiExpressionList argumentList = newExpression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
final PsiExpression arg = expressions[i];
|
||||
final PsiType argType = arg.getType();
|
||||
if (argType == null) {
|
||||
return false;
|
||||
}
|
||||
if (CollectionUtils.isCollectionClassOrInterface(argType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameterList;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RenameFix;
|
||||
|
||||
public class MisspelledCompareToInspection extends MethodInspection {
|
||||
private final RenameFix fix = new RenameFix("compareTo");
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'compareto()' instead of 'compareTo()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref() method should probably be compareTo() #loc";
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MisspelledCompareToVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MisspelledCompareToVisitor extends BaseInspectionVisitor {
|
||||
private MisspelledCompareToVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//note: no call to super
|
||||
final String methodName = method.getName();
|
||||
if (!"compareto".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParameters().length != 1) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameterList;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RenameFix;
|
||||
|
||||
public class MisspelledEqualsInspection extends MethodInspection {
|
||||
private final RenameFix fix = new RenameFix("equals");
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'equal()' instead of 'equals()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref() method should probably be equals() #loc";
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MisspelledToStringVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MisspelledToStringVisitor extends BaseInspectionVisitor {
|
||||
private MisspelledToStringVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//note: no call to super
|
||||
final String methodName = method.getName();
|
||||
if (!"equal".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParameters().length != 1) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameterList;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RenameFix;
|
||||
|
||||
public class MisspelledHashcodeInspection extends MethodInspection {
|
||||
private final RenameFix fix = new RenameFix("hashCode");
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'hashcode()' instead of 'hashCode()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref() should probably be hashCode() #loc";
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MisspelledHashcodeVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MisspelledHashcodeVisitor extends BaseInspectionVisitor {
|
||||
private MisspelledHashcodeVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//note: no call to super
|
||||
final String methodName = method.getName();
|
||||
if (!"hashcode".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParameters().length != 0) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameterList;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RenameFix;
|
||||
|
||||
public class MisspelledToStringInspection extends MethodInspection {
|
||||
private final RenameFix fix = new RenameFix("toString");
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'tostring()' instead of 'toString()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref() method should probably be toString() #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MisspelledToStringVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MisspelledToStringVisitor extends BaseInspectionVisitor {
|
||||
private MisspelledToStringVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//note: no call to super
|
||||
final String methodName = method.getName();
|
||||
if (!"tostring".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParameters().length != 0) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.siyeh.ig.*;
|
||||
|
||||
public class NonShortCircuitBooleanInspection extends ExpressionInspection {
|
||||
private final InspectionGadgetsFix fix = new NonShortCircuitBooleanFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Non-short-circuit boolean expression";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Non-short-circuit boolean expression #loc";
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class NonShortCircuitBooleanFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Replace with short circuit expression";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
if (descriptor.getPsiElement() instanceof PsiBinaryExpression) {
|
||||
final PsiBinaryExpression expression = (PsiBinaryExpression) descriptor.getPsiElement();
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
final PsiJavaToken operationSign = expression.getOperationSign();
|
||||
final IElementType tokenType = operationSign.getTokenType();
|
||||
final String newExpression = lhs.getText() + getShortCircuitOperand(tokenType) + rhs.getText();
|
||||
replaceExpression(project, expression, newExpression);
|
||||
} else {
|
||||
final PsiAssignmentExpression expression = (PsiAssignmentExpression) descriptor.getPsiElement();
|
||||
final PsiExpression lhs = expression.getLExpression();
|
||||
final PsiExpression rhs = expression.getRExpression();
|
||||
final PsiJavaToken operationSign = expression.getOperationSign();
|
||||
final IElementType tokenType = operationSign.getTokenType();
|
||||
final String newExpression = lhs.getText() + getShortCircuitOperand(tokenType) + rhs.getText();
|
||||
replaceExpression(project, expression, newExpression);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getShortCircuitOperand(IElementType tokenType) {
|
||||
if (tokenType.equals(JavaTokenType.AND)) {
|
||||
return "&&";
|
||||
}
|
||||
if (tokenType.equals(JavaTokenType.ANDEQ)) {
|
||||
return "&&=";
|
||||
}
|
||||
if (tokenType.equals(JavaTokenType.OR)) {
|
||||
return "||";
|
||||
}
|
||||
return "||=";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new NonShortCircuitBooleanVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class NonShortCircuitBooleanVisitor extends BaseInspectionVisitor {
|
||||
private NonShortCircuitBooleanVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.AND) &&
|
||||
!tokenType.equals(JavaTokenType.OR)) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = expression.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
if (!type.equals(PsiType.BOOLEAN)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
if (!tokenType.equals(JavaTokenType.ANDEQ) &&
|
||||
!tokenType.equals(JavaTokenType.OREQ)) {
|
||||
return;
|
||||
}
|
||||
final PsiType type = expression.getType();
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
if (!type.equals(PsiType.BOOLEAN)) {
|
||||
return;
|
||||
}
|
||||
registerError(expression);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.ui.SingleCheckboxOptionsPanel;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ComparisonUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class ObjectEqualityInspection extends ExpressionInspection {
|
||||
public boolean m_ignoreEnums = false;
|
||||
|
||||
private final EqualityToEqualsFix fix = new EqualityToEqualsFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Object comparison using ==, instead of '.equals()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel("Ignore == between enumerated types",
|
||||
this, "m_ignoreEnums");
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Object values are compared using '#ref', not '.equals()' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ObjectEqualityVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private class EqualityToEqualsFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Replace with .equals()";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement comparisonToken = descriptor.getPsiElement();
|
||||
final PsiBinaryExpression
|
||||
expression = (PsiBinaryExpression) comparisonToken.getParent();
|
||||
boolean negated = false;
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
if (sign.getTokenType() == JavaTokenType.NE) {
|
||||
negated = true;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
if (lhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedLhs = ParenthesesUtils.stripParentheses(lhs);
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedRhs = ParenthesesUtils.stripParentheses(rhs);
|
||||
|
||||
final String expString;
|
||||
if (ParenthesesUtils.getPrecendence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
expString = '(' + strippedLhs.getText() + ").equals(" + strippedRhs.getText() + ')';
|
||||
} else {
|
||||
expString = strippedLhs.getText() + ".equals(" + strippedRhs.getText() + ')';
|
||||
}
|
||||
final String newExpression;
|
||||
if (negated) {
|
||||
newExpression = '!' + expString;
|
||||
} else {
|
||||
newExpression = expString;
|
||||
}
|
||||
replaceExpression(project, expression, newExpression);
|
||||
}
|
||||
}
|
||||
|
||||
private class ObjectEqualityVisitor extends BaseInspectionVisitor {
|
||||
private ObjectEqualityVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
if (!ComparisonUtils.isEqualityComparison(expression)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (!isObjectType(rhs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
if (!isObjectType(lhs)) {
|
||||
return;
|
||||
}
|
||||
if (m_ignoreEnums && isEnumType(rhs) && isEnumType(lhs)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = (PsiMethod) PsiTreeUtil.getParentOfType(expression, PsiMethod.class);
|
||||
final String methodName = method.getName();
|
||||
if ("equals".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign == null) {
|
||||
return;
|
||||
}
|
||||
registerError(sign);
|
||||
}
|
||||
|
||||
private boolean isEnumType(PsiExpression exp) {
|
||||
if (exp == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType type = exp.getType();
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
if(!(type instanceof PsiClassType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final PsiClass aClass = ((PsiClassType)type).resolve();
|
||||
if(aClass == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return aClass.isEnum();
|
||||
}
|
||||
|
||||
private boolean isObjectType(PsiExpression exp) {
|
||||
if (exp == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType type = exp.getType();
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
return !ClassUtils.isPrimitive(type)
|
||||
&& !type.equals(PsiType.NULL)
|
||||
&& !TypeUtils.isJavaLangString(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class ObjectEqualsNullInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Object.equals(null)";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return ".equals(#ref) is probably not what was intended #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ObjectEqualsNullVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ObjectEqualsNullVisitor extends BaseInspectionVisitor {
|
||||
private ObjectEqualsNullVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression call) {
|
||||
super.visitMethodCallExpression(call);
|
||||
final PsiReferenceExpression methodExpression = call.getMethodExpression();
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (!"equals".equals(methodName)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList = call.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
if (args.length != 1) {
|
||||
return;
|
||||
}
|
||||
if (!isNull(args[0])) {
|
||||
return;
|
||||
}
|
||||
registerError(args[0]);
|
||||
}
|
||||
|
||||
private static boolean isNull(PsiExpression arg) {
|
||||
if (!(arg instanceof PsiLiteralExpression)) {
|
||||
return false;
|
||||
}
|
||||
final String text = arg.getText();
|
||||
return "null".equals(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class OctalAndDecimalIntegersMixedInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Octal and decimal integers in same array";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Octal and decimal integers are in the same array initializer #loc ";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new OctalAndDecimalIntegersMixedVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class OctalAndDecimalIntegersMixedVisitor extends BaseInspectionVisitor {
|
||||
private OctalAndDecimalIntegersMixedVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
|
||||
super.visitArrayInitializerExpression(expression);
|
||||
final PsiExpression[] initializers = expression.getInitializers();
|
||||
boolean hasDecimalLiteral = false;
|
||||
boolean hasOctalLiteral = false;
|
||||
for (int i = 0; i < initializers.length; i++) {
|
||||
final PsiExpression initializer = initializers[i];
|
||||
if (initializer instanceof PsiLiteralExpression) {
|
||||
final PsiLiteralExpression literal = (PsiLiteralExpression) initializer;
|
||||
if (isDecimalLiteral(literal)) {
|
||||
hasDecimalLiteral = true;
|
||||
}
|
||||
if (isOctalLiteral(literal)) {
|
||||
hasOctalLiteral = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasOctalLiteral && hasDecimalLiteral) {
|
||||
registerError(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDecimalLiteral(PsiLiteralExpression literal) {
|
||||
final PsiType type = literal.getType();
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
if (!type.equals(PsiType.INT) &&
|
||||
!type.equals(PsiType.LONG)) {
|
||||
return false;
|
||||
}
|
||||
final String text = literal.getText();
|
||||
if ("0".equals(text)) {
|
||||
return false;
|
||||
}
|
||||
return text.charAt(0) != '0';
|
||||
}
|
||||
|
||||
private static boolean isOctalLiteral(PsiLiteralExpression literal) {
|
||||
final PsiType type = literal.getType();
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(type.equals(PsiType.INT)
|
||||
|| type.equals(PsiType.LONG))) {
|
||||
return false;
|
||||
}
|
||||
final String text = literal.getText();
|
||||
if ("0".equals(text) || "0L".equals(text)) {
|
||||
return false;
|
||||
}
|
||||
return text.charAt(0) == '0' && !text.startsWith("0x") && !text.startsWith("0X");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class ResultOfObjectAllocationIgnoredInspection extends ExpressionInspection {
|
||||
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Result of object allocation ignored";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "result of new #ref() is ignored. #loc ";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new IgnoreResultOfCallVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class IgnoreResultOfCallVisitor extends BaseInspectionVisitor {
|
||||
private IgnoreResultOfCallVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitExpressionStatement(PsiExpressionStatement statement) {
|
||||
super.visitExpressionStatement(statement);
|
||||
if (!(statement.getExpression() instanceof PsiNewExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiNewExpression newExpression = (PsiNewExpression) statement.getExpression();
|
||||
final PsiExpression[] arrayDimensions = newExpression.getArrayDimensions();
|
||||
if (arrayDimensions != null && arrayDimensions.length != 0) {
|
||||
return;
|
||||
}
|
||||
if (newExpression.getArrayInitializer() != null) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaCodeReferenceElement classReference =
|
||||
newExpression.getClassReference();
|
||||
registerError(classReference);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.IsConstantExpressionVisitor;
|
||||
import com.intellij.psi.util.ConstantExpressionUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class ResultSetIndexZeroInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Use on index 0 with JDBC ResultSet";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Use on index 0 with JDBC ResultSet #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ResultSetIndexZeroVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ResultSetIndexZeroVisitor extends BaseInspectionVisitor {
|
||||
private ResultSetIndexZeroVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
if (methodExpression == null) {
|
||||
return;
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
if (!methodName.startsWith("get") && !methodName.startsWith("update") ) {
|
||||
return;
|
||||
}
|
||||
final PsiExpressionList argumentList = expression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
if (args == null) {
|
||||
return;
|
||||
}
|
||||
if(args.length== 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
final PsiExpression arg = args[0];
|
||||
if (!TypeUtils.expressionHasType("int", arg)) {
|
||||
return;
|
||||
}
|
||||
if(!isConstant(arg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
final Integer val = (Integer) ConstantExpressionUtil.computeCastTo(arg, PsiType.INT);
|
||||
if(val == null || val.intValue()!=0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (!TypeUtils.expressionHasTypeOrSubtype("java.sql.ResultSet", qualifier)) {
|
||||
return;
|
||||
}
|
||||
registerError(arg);
|
||||
}
|
||||
|
||||
private static boolean isConstant(PsiExpression expression) {
|
||||
if (expression == null) {
|
||||
return false;
|
||||
}
|
||||
final IsConstantExpressionVisitor visitor =
|
||||
new IsConstantExpressionVisitor();
|
||||
expression.accept(visitor);
|
||||
return visitor.isConstant();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.*;
|
||||
|
||||
public class ReturnNullInspection extends StatementInspection {
|
||||
public boolean m_reportObjectMethods = true;
|
||||
public boolean m_reportArrayMethods = true;
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Return of 'null'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Return of '#ref' #loc";
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
final GridBagLayout layout = new GridBagLayout();
|
||||
final JPanel panel = new JPanel(layout);
|
||||
final JCheckBox arrayCheckBox = new JCheckBox("Methods that return arrays", m_reportArrayMethods);
|
||||
final ButtonModel arrayModel = arrayCheckBox.getModel();
|
||||
arrayModel.addChangeListener(new ChangeListener() {
|
||||
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
m_reportArrayMethods = arrayModel.isSelected();
|
||||
}
|
||||
});
|
||||
final JCheckBox objectCheckBox = new JCheckBox("Methods that return objects", m_reportObjectMethods);
|
||||
final ButtonModel model = objectCheckBox.getModel();
|
||||
model.addChangeListener(new ChangeListener() {
|
||||
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
m_reportObjectMethods = model.isSelected();
|
||||
}
|
||||
});
|
||||
final GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.gridx = 0;
|
||||
constraints.gridy = 0;
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
panel.add(arrayCheckBox, constraints);
|
||||
|
||||
constraints.gridx = 0;
|
||||
constraints.gridy = 1;
|
||||
panel.add(objectCheckBox, constraints);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ReturnNullVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private class ReturnNullVisitor extends BaseInspectionVisitor {
|
||||
private ReturnNullVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitLiteralExpression(PsiLiteralExpression value) {
|
||||
super.visitLiteralExpression(value);
|
||||
final String text = value.getText();
|
||||
if (!"null".equals(text)) {
|
||||
return;
|
||||
}
|
||||
PsiElement parent = value.getParent();
|
||||
while (parent != null &&
|
||||
(parent instanceof PsiParenthesizedExpression ||
|
||||
parent instanceof PsiConditionalExpression ||
|
||||
parent instanceof PsiTypeCastExpression)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent == null || !(parent instanceof PsiReturnStatement)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = (PsiMethod) PsiTreeUtil.getParentOfType(value, PsiMethod.class);
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (returnType == null) {
|
||||
return;
|
||||
}
|
||||
final boolean isArray = returnType.getArrayDimensions() > 0;
|
||||
if (m_reportArrayMethods && isArray) {
|
||||
registerError(value);
|
||||
}
|
||||
if (m_reportObjectMethods && !isArray) {
|
||||
registerError(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ComparisonUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class StringEqualityInspection extends ExpressionInspection {
|
||||
private final EqualityToEqualsFix fix = new EqualityToEqualsFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "String comparison using ==, instead of '.equals()'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "String values are compared using '#ref', not '.equals()' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ObjectEqualityVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class EqualityToEqualsFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Replace with .equals()";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement comparisonToken = descriptor.getPsiElement();
|
||||
boolean negated = false;
|
||||
final PsiBinaryExpression expression =
|
||||
(PsiBinaryExpression) comparisonToken.getParent();
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
if (sign.getTokenType() == JavaTokenType.NE) {
|
||||
negated = true;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
if (lhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedLhs = ParenthesesUtils.stripParentheses(lhs);
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (rhs == null) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression strippedRhs = ParenthesesUtils.stripParentheses(rhs);
|
||||
|
||||
final String expString;
|
||||
if (ParenthesesUtils.getPrecendence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) {
|
||||
expString = '(' + strippedLhs.getText() + ").equals(" + strippedRhs.getText() + ')';
|
||||
} else {
|
||||
expString = strippedLhs.getText() + ".equals(" + strippedRhs.getText() + ')';
|
||||
}
|
||||
final String newExpression;
|
||||
if (negated) {
|
||||
newExpression = '!' + expString;
|
||||
} else {
|
||||
newExpression = expString;
|
||||
}
|
||||
replaceExpression(project, expression, newExpression);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ObjectEqualityVisitor extends BaseInspectionVisitor {
|
||||
private ObjectEqualityVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
if (!ComparisonUtils.isEqualityComparison(expression)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lhs = expression.getLOperand();
|
||||
if (!isStringType(lhs)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression rhs = expression.getROperand();
|
||||
if (!isStringType(rhs)) {
|
||||
return;
|
||||
}
|
||||
final String lhsText = lhs.getText();
|
||||
if ("null".equals(lhsText)) {
|
||||
return;
|
||||
}
|
||||
final String rhsText = rhs.getText();
|
||||
if ("null".equals(rhsText)) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaToken sign = expression.getOperationSign();
|
||||
registerError(sign);
|
||||
}
|
||||
|
||||
private static boolean isStringType(PsiExpression lhs) {
|
||||
if (lhs == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType lhsType = lhs.getType();
|
||||
if (lhsType == null) {
|
||||
return false;
|
||||
}
|
||||
return !ClassUtils.isPrimitive(lhsType)
|
||||
&& !lhsType.equals(PsiType.NULL)
|
||||
&& TypeUtils.isJavaLangString(lhsType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ExpressionInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
|
||||
public class SubtractionInCompareToInspection extends ExpressionInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Subtraction in compareTo()";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Subtraction (#ref) in compareTo() may result in overflow errors #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new SubtractionInCompareToVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class SubtractionInCompareToVisitor extends BaseInspectionVisitor {
|
||||
private SubtractionInCompareToVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitBinaryExpression(PsiBinaryExpression exp) {
|
||||
super.visitBinaryExpression(exp);
|
||||
if (!isSubtraction(exp)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method =
|
||||
(PsiMethod) PsiTreeUtil.getParentOfType(exp, PsiMethod.class);
|
||||
if (!isCompareTo(method)) {
|
||||
return;
|
||||
}
|
||||
registerError(exp);
|
||||
}
|
||||
|
||||
private static boolean isCompareTo(PsiMethod method) {
|
||||
if (method == null) {
|
||||
return false;
|
||||
}
|
||||
final String methodName = method.getName();
|
||||
if (!"compareTo".equals(methodName)) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
if (parameters.length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (!TypeUtils.typeEquals("int", returnType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isSubtraction(PsiBinaryExpression exp) {
|
||||
final PsiExpression lhs = exp.getLOperand();
|
||||
if (lhs == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression rhs = exp.getROperand();
|
||||
if (rhs == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiJavaToken sign = exp.getOperationSign();
|
||||
if (sign == null) {
|
||||
return false;
|
||||
}
|
||||
final IElementType tokenType = sign.getTokenType();
|
||||
return tokenType.equals(JavaTokenType.MINUS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
import com.siyeh.ig.ui.SingleCheckboxOptionsPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class SwitchStatementsWithoutDefaultInspection extends StatementInspection {
|
||||
private boolean m_ignoreFullyCoveredEnums = true;
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'switch' statement without 'default' branch";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'#ref' statement without 'default' branch #loc";
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel("Ignore if all cases of an enumerated type are covered",
|
||||
this, "m_ignoreFullyCoveredEnums");
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new SwitchStatementsWithoutDefaultVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private class SwitchStatementsWithoutDefaultVisitor extends BaseInspectionVisitor {
|
||||
private SwitchStatementsWithoutDefaultVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(PsiSwitchStatement statement) {
|
||||
super.visitSwitchStatement(statement);
|
||||
if (switchStatementHasDefault(statement)) {
|
||||
return;
|
||||
}
|
||||
if (m_ignoreFullyCoveredEnums && switchStatementIsFullyCoveredEnum(statement)) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
}
|
||||
|
||||
private boolean switchStatementHasDefault(PsiSwitchStatement statement) {
|
||||
final PsiCodeBlock body = statement.getBody();
|
||||
if (body == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
final PsiStatement child = statements[i];
|
||||
if (child instanceof PsiSwitchLabelStatement &&
|
||||
((PsiSwitchLabelStatement) child).isDefaultCase()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean switchStatementIsFullyCoveredEnum(PsiSwitchStatement statement) {
|
||||
final PsiExpression expression = statement.getExpression();
|
||||
if (expression == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiType type = expression.getType();
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(type instanceof PsiClassType)) {
|
||||
return false;
|
||||
}
|
||||
final PsiClass aClass = ((PsiClassType) type).resolve();
|
||||
if (aClass == null) {
|
||||
return false;
|
||||
}
|
||||
if (!aClass.isEnum()) {
|
||||
return false;
|
||||
}
|
||||
int numCases = 0;
|
||||
final PsiCodeBlock body = statement.getBody();
|
||||
if (body == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
if (statements == null) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
final PsiStatement child = statements[i];
|
||||
if (child instanceof PsiSwitchLabelStatement) {
|
||||
numCases++;
|
||||
}
|
||||
}
|
||||
final PsiField[] fields = aClass.getFields();
|
||||
int numEnums = 0;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
final PsiField field = fields[i];
|
||||
final PsiType fieldType = field.getType();
|
||||
if (fieldType.equals(type)) {
|
||||
numEnums++;
|
||||
}
|
||||
|
||||
}
|
||||
return numEnums == numCases;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.StatementInspection;
|
||||
|
||||
public class TextLabelInSwitchStatementInspection extends StatementInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Text label in 'switch' statement";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Text label #ref: in 'switch' statement #loc ";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new TextLabelInSwitchStatementVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class TextLabelInSwitchStatementVisitor extends BaseInspectionVisitor {
|
||||
private TextLabelInSwitchStatementVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitSwitchStatement(PsiSwitchStatement statement) {
|
||||
super.visitSwitchStatement(statement);
|
||||
final PsiCodeBlock body = statement.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
if (statements == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < statements.length; i++) {
|
||||
checkForLabel(statements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForLabel(PsiStatement statement) {
|
||||
if (!(statement instanceof PsiLabeledStatement)) {
|
||||
return;
|
||||
}
|
||||
final PsiIdentifier label = ((PsiLabeledStatement) statement).getLabelIdentifier();
|
||||
registerError(label);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class AbstractClassExtendsConcreteClassInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Abstract class extends concrete class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class #ref is declared 'abstract', and extends a concrete class #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AbstractClassExtendsConcreteClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AbstractClassExtendsConcreteClassVisitor extends BaseInspectionVisitor {
|
||||
private AbstractClassExtendsConcreteClassVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (aClass.isInterface()|| aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass superClass = aClass.getSuperClass();
|
||||
if (superClass == null) {
|
||||
return;
|
||||
}
|
||||
if (superClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
final String superclassName = superClass.getQualifiedName();
|
||||
if ("java.lang.Object".equals(superclassName)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiSuperMethodUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AbstractClassWithoutAbstractMethodsInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Abstract class without abstract methods";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class #ref is declared 'abstract', and has no 'abstract' methods #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AbstractClassWithoutAbstractMethodsVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AbstractClassWithoutAbstractMethodsVisitor extends BaseInspectionVisitor {
|
||||
private AbstractClassWithoutAbstractMethodsVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (aClass.isInterface() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
if (hasAbstractMethods(aClass)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
private static boolean hasAbstractMethods(PsiClass aClass) {
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
final Set overriddenMethods = calculateOverriddenMethods(methods);
|
||||
final PsiMethod[] allMethods = aClass.getAllMethods();
|
||||
for (int i = 0; i < allMethods.length; i++) {
|
||||
final PsiMethod method = allMethods[i];
|
||||
if (method.hasModifierProperty(PsiModifier.ABSTRACT) &&
|
||||
!overriddenMethods.contains(method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Set calculateOverriddenMethods(PsiMethod[] methods) {
|
||||
final Set overriddenMethods = new HashSet(methods.length);
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
final PsiMethod method = methods[i];
|
||||
calculateOverriddenMethods(method, overriddenMethods);
|
||||
}
|
||||
return overriddenMethods;
|
||||
}
|
||||
|
||||
private static void calculateOverriddenMethods(PsiMethod method, Set overriddenMethods) {
|
||||
final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
|
||||
for (int j = 0; j < superMethods.length; j++) {
|
||||
final PsiMethod superMethod = superMethods[j];
|
||||
overriddenMethods.add(superMethod);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiSuperMethodUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.siyeh.ig.*;
|
||||
|
||||
public class AbstractMethodOverridesAbstractMethodInspection extends MethodInspection {
|
||||
private final AbstractMethodOverridesAbstractMethodFix fix = new AbstractMethodOverridesAbstractMethodFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Abstract method overrides abstract method";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Abstract method '#ref' overrides abstract method #loc";
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class AbstractMethodOverridesAbstractMethodFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Remove redundant abstract method declaration";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement methodNameIdentifier = descriptor.getPsiElement();
|
||||
final PsiElement method = methodNameIdentifier.getParent();
|
||||
deleteElement(method);
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AbstractMethodOverridesAbstractMethodVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AbstractMethodOverridesAbstractMethodVisitor extends BaseInspectionVisitor {
|
||||
private AbstractMethodOverridesAbstractMethodVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (method.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (!method.hasModifierProperty(PsiModifier.ABSTRACT) &&
|
||||
!containingClass.isInterface()) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
|
||||
for (int i = 0; i < superMethods.length; i++) {
|
||||
final PsiMethod superMethod = superMethods[i];
|
||||
final PsiClass superClass = superMethod.getContainingClass();
|
||||
if (superClass.isInterface() ||
|
||||
superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
registerMethodError(method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiSuperMethodUtil;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
|
||||
public class AbstractMethodOverridesConcreteMethodInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Abstract method overrides concrete method";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Abstract method '#ref' overrides concrete method #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AbstractMethodOverridesConcreteMethodVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AbstractMethodOverridesConcreteMethodVisitor extends BaseInspectionVisitor {
|
||||
private AbstractMethodOverridesConcreteMethodVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (method.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass.isInterface() || containingClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!method.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
|
||||
for (int i = 0; i < superMethods.length; i++) {
|
||||
final PsiMethod superMethod = superMethods[i];
|
||||
final PsiClass superClass = superMethod.getContainingClass();
|
||||
if (!superClass.isInterface() &&
|
||||
!superMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
registerMethodError(method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class AnonymousInnerClassInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Anonymous inner class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Anonymous inner class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new AnonymousInnerClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class AnonymousInnerClassVisitor extends BaseInspectionVisitor {
|
||||
private AnonymousInnerClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
//no call to super here, to avoid double counting
|
||||
}
|
||||
|
||||
public void visitAnonymousClass(PsiAnonymousClass aClass) {
|
||||
super.visitAnonymousClass(aClass);
|
||||
final PsiJavaCodeReferenceElement classReference = aClass.getBaseClassReference();
|
||||
registerError(classReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.MoveClassFix;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
|
||||
public class ClassInTopLevelPackageInspection extends ClassInspection {
|
||||
private final MoveClassFix fix = new MoveClassFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Class without package statement";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class #ref lacks a package statement #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ClassInTopLevelPackageVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class ClassInTopLevelPackageVisitor extends BaseInspectionVisitor {
|
||||
private ClassInTopLevelPackageVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (ClassUtils.isInnerClass(aClass)) {
|
||||
return;
|
||||
}
|
||||
final PsiFile file = aClass.getContainingFile();
|
||||
|
||||
if (file == null || !(file instanceof PsiJavaFile)) {
|
||||
return;
|
||||
}
|
||||
if (((PsiJavaFile) file).getPackageStatement() != null) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.*;
|
||||
|
||||
public class ClassInitializerInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Non-static initializer";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Non-static initializer #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ClassInitializerVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ClassInitializerVisitor extends BaseInspectionVisitor {
|
||||
private ClassInitializerVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
final PsiClassInitializer[] initializers = aClass.getInitializers();
|
||||
for (int i = 0; i < initializers.length; i++) {
|
||||
final PsiClassInitializer initializer = initializers[i];
|
||||
if (!initializer.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
final PsiCodeBlock body = initializer.getBody();
|
||||
final PsiJavaToken leftBrace = body.getLBrace();
|
||||
registerError(leftBrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.*;
|
||||
|
||||
public class ClassMayBeInterfaceInspection extends ClassInspection {
|
||||
private final ClassMayBeInterfaceFix fix = new ClassMayBeInterfaceFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Class may be interface";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref may be interface #loc";
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class ClassMayBeInterfaceFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Convert class to interface";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor problemDescriptor) {
|
||||
final PsiIdentifier classNameIdentifier = (PsiIdentifier) problemDescriptor.getPsiElement();
|
||||
final PsiClass interfaceClass = (PsiClass) classNameIdentifier.getParent();
|
||||
try {
|
||||
moveSubClassExtendsToImplements(interfaceClass);
|
||||
changeClassToInterface(interfaceClass);
|
||||
moveImplementsToExtends(interfaceClass);
|
||||
} catch (IncorrectOperationException e) {
|
||||
final Class aClass = getClass();
|
||||
final String className = aClass.getName();
|
||||
final Logger logger = Logger.getInstance(className);
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void changeClassToInterface(PsiClass aClass)
|
||||
throws IncorrectOperationException {
|
||||
final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
|
||||
final PsiKeyword classKeyword = (PsiKeyword)PsiTreeUtil.getPrevSiblingOfType(nameIdentifier, PsiKeyword.class);
|
||||
final PsiManager manager = aClass.getManager();
|
||||
final PsiElementFactory factory = manager.getElementFactory();
|
||||
final PsiKeyword interfaceKeyword = factory.createKeyword("interface");
|
||||
classKeyword.replace(interfaceKeyword);
|
||||
}
|
||||
|
||||
private static void moveImplementsToExtends(PsiClass anInterface)
|
||||
throws IncorrectOperationException {
|
||||
final PsiReferenceList extendsList = anInterface.getExtendsList();
|
||||
final PsiReferenceList implementsList = anInterface.getImplementsList();
|
||||
final PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements();
|
||||
for (int i = 0; i < referenceElements.length; i++) {
|
||||
final PsiJavaCodeReferenceElement referenceElement = referenceElements[i];
|
||||
final PsiElement elementCopy = referenceElement.copy();
|
||||
extendsList.add(elementCopy);
|
||||
referenceElement.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static void moveSubClassExtendsToImplements(PsiClass oldClass)
|
||||
throws IncorrectOperationException {
|
||||
final PsiManager psiManager = oldClass.getManager();
|
||||
final PsiSearchHelper searchHelper = psiManager.getSearchHelper();
|
||||
final PsiElementFactory elementFactory = psiManager.getElementFactory();
|
||||
final PsiJavaCodeReferenceElement classReference = elementFactory.createClassReferenceElement(oldClass);
|
||||
final GlobalSearchScope searchScope = oldClass.getUseScope();
|
||||
final PsiClass[] inheritors = searchHelper.findInheritors(oldClass, searchScope, false);
|
||||
for (int i = 0; i < inheritors.length; i++) {
|
||||
final PsiClass inheritor = inheritors[i];
|
||||
final PsiReferenceList extendsList = inheritor.getExtendsList();
|
||||
removeReference(extendsList, classReference);
|
||||
final PsiReferenceList implementsList = inheritor.getImplementsList();
|
||||
implementsList.add(classReference);
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeReference(PsiReferenceList referenceList,
|
||||
PsiJavaCodeReferenceElement reference)
|
||||
throws IncorrectOperationException {
|
||||
final PsiJavaCodeReferenceElement[] implementsReferences = referenceList.getReferenceElements();
|
||||
final String fqName = reference.getQualifiedName();
|
||||
for (int j = 0; j < implementsReferences.length; j++) {
|
||||
final PsiJavaCodeReferenceElement implementsReference = implementsReferences[j];
|
||||
final String implementsReferenceFqName = implementsReference.getQualifiedName();
|
||||
if (fqName.equals(implementsReferenceFqName)) {
|
||||
implementsReference.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ClassMayBeInterfaceVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ClassMayBeInterfaceVisitor extends BaseInspectionVisitor {
|
||||
private ClassMayBeInterfaceVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (aClass.isInterface() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (aClass.isEnum() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!mayBeInterface(aClass)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
public static boolean mayBeInterface(PsiClass aClass) {
|
||||
final PsiReferenceList extendsList = aClass.getExtendsList();
|
||||
|
||||
if (extendsList != null) {
|
||||
final PsiJavaCodeReferenceElement[] extendsElements = extendsList.getReferenceElements();
|
||||
if (extendsElements != null && extendsElements.length > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final PsiClassInitializer[] initializers = aClass.getInitializers();
|
||||
if (initializers != null && initializers.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (!allMethodsPublicAbstract(aClass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!allFieldsPublicStaticFinal(aClass)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean allFieldsPublicStaticFinal(PsiClass aClass) {
|
||||
boolean allFieldsStaticFinal = true;
|
||||
final PsiField[] fields = aClass.getFields();
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
final PsiField field = fields[i];
|
||||
if (!(field.hasModifierProperty(PsiModifier.STATIC)
|
||||
&& field.hasModifierProperty(PsiModifier.FINAL)
|
||||
&& field.hasModifierProperty(PsiModifier.PUBLIC))) {
|
||||
allFieldsStaticFinal = false;
|
||||
}
|
||||
}
|
||||
return allFieldsStaticFinal;
|
||||
}
|
||||
|
||||
private static boolean allMethodsPublicAbstract(PsiClass aClass) {
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
final PsiMethod method = methods[i];
|
||||
if (!(method.hasModifierProperty(PsiModifier.ABSTRACT) &&
|
||||
method.hasModifierProperty(PsiModifier.PUBLIC))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class ClassNameDiffersFromFileNameInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Class name differs from file name";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class name #ref differs from file name #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new classNameDiffersFromFileName(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class classNameDiffersFromFileName extends BaseInspectionVisitor {
|
||||
|
||||
private classNameDiffersFromFileName(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (!(aClass.getParent() instanceof PsiJavaFile)) {
|
||||
return;
|
||||
}
|
||||
final PsiJavaFile file = (PsiJavaFile) aClass.getParent();
|
||||
final String className = aClass.getName();
|
||||
if (className == null) {
|
||||
return;
|
||||
}
|
||||
final String fileName = file.getName();
|
||||
if (fileName == null) {
|
||||
return;
|
||||
}
|
||||
final int prefixIndex = fileName.indexOf((int) '.');
|
||||
final String filenameWithoutPrefix = fileName.substring(0, prefixIndex);
|
||||
if (className.equals(filenameWithoutPrefix)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.*;
|
||||
|
||||
public class ClassWithoutConstructorInspection extends ClassInspection {
|
||||
private final ClassWithoutConstructorFix fix = new ClassWithoutConstructorFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Class without constructor";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref has no constructor #loc";
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class ClassWithoutConstructorFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Create empty constructor";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
try {
|
||||
final PsiElement classIdentifier = descriptor.getPsiElement();
|
||||
final PsiClass psiClass = (PsiClass) classIdentifier.getParent();
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
final PsiElementFactory factory = psiManager.getElementFactory();
|
||||
final PsiMethod constructor = factory.createConstructor();
|
||||
psiClass.add(constructor);
|
||||
final CodeStyleManager styleManager = psiManager.getCodeStyleManager();
|
||||
styleManager.reformat(constructor);
|
||||
} catch (IncorrectOperationException e) {
|
||||
final Class aClass = getClass();
|
||||
final String className = aClass.getName();
|
||||
final Logger logger = Logger.getInstance(className);
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ClassWithoutConstructorVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ClassWithoutConstructorVisitor extends BaseInspectionVisitor {
|
||||
private ClassWithoutConstructorVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so it doesn't drill down
|
||||
if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (aClass.getNameIdentifier() == null) {
|
||||
return; //a very hacky test for anonymous classes
|
||||
}
|
||||
if (classHasConstructor(aClass)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
private static boolean classHasConstructor(PsiClass aClass) {
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
final PsiMethod method = methods[i];
|
||||
if (method.isConstructor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class ClassWithoutNoArgConstructorInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Class without no-arg constructor";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "#ref has no no-arg constructor #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ClassWithoutNoArgConstructorVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ClassWithoutNoArgConstructorVisitor extends BaseInspectionVisitor {
|
||||
private ClassWithoutNoArgConstructorVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so it doesn't drill down
|
||||
if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (aClass.getNameIdentifier() == null) {
|
||||
return; //a very hacky test for anonymous classes
|
||||
}
|
||||
if (classHasNoArgConstructor(aClass)) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
private static boolean classHasNoArgConstructor(PsiClass aClass) {
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
final PsiMethod method = methods[i];
|
||||
if (method.isConstructor()) {
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList != null) {
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
if (parameters != null && parameters.length == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.FieldInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class ConstantDeclaredInAbstractClassInspection extends FieldInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Constant declared in abstract class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Constant '#ref' declared in abstract class #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ConstantDeclaredInAbstractClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ConstantDeclaredInAbstractClassVisitor extends BaseInspectionVisitor {
|
||||
private ConstantDeclaredInAbstractClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!field.hasModifierProperty(PsiModifier.STATIC) ||
|
||||
!field.hasModifierProperty(PsiModifier.PUBLIC) ||
|
||||
!field.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = field.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (containingClass.isInterface() || containingClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
registerFieldError(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.FieldInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class ConstantDeclaredInInterfaceInspection extends FieldInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Constant declared in interface";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Constant '#ref' declared in interface #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ConstantDeclaredInInterfaceVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class ConstantDeclaredInInterfaceVisitor extends BaseInspectionVisitor {
|
||||
private ConstantDeclaredInInterfaceVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
final PsiClass containingClass = field.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.isInterface() && !containingClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
registerFieldError(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class EmptyClassInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Empty class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class #ref is empty #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new EmptyClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class EmptyClassVisitor extends BaseInspectionVisitor {
|
||||
private EmptyClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
//don't call super, to prevent drilldown
|
||||
if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] constructors = aClass.getConstructors();
|
||||
if (constructors != null && constructors.length > 0) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
if (methods != null && methods.length > 0) {
|
||||
return;
|
||||
}
|
||||
final PsiField[] fields = aClass.getFields();
|
||||
if (fields != null && fields.length > 0) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RemoveModifierFix;
|
||||
|
||||
public class FinalClassInspection extends MethodInspection {
|
||||
private static final Logger s_logger =
|
||||
Logger.getInstance("FinalClassInspection");
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'final' class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class declared '#ref' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FinalStaticMethodVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return new RemoveModifierFix(location);
|
||||
}
|
||||
|
||||
private static class FinalStaticMethodVisitor extends BaseInspectionVisitor {
|
||||
private FinalStaticMethodVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
//no call to super, so we don't drill into inner classes
|
||||
if (!aClass.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.FINAL, aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RemoveModifierFix;
|
||||
|
||||
public class FinalMethodInFinalClassInspection extends MethodInspection {
|
||||
public String getDisplayName() {
|
||||
return "'final' method in 'final' class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Method declared '#ref' in 'final' class #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FinalMethodInFinalClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return new RemoveModifierFix(location);
|
||||
}
|
||||
|
||||
private static class FinalMethodInFinalClassVisitor extends BaseInspectionVisitor {
|
||||
private FinalMethodInFinalClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!method.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.FINAL, method);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RemoveModifierFix;
|
||||
|
||||
public class FinalMethodInspection extends MethodInspection {
|
||||
private static final Logger s_logger =
|
||||
Logger.getInstance("FinalMethodnspection");
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'final' method";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Method declared '#ref' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FinalMethodVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return new RemoveModifierFix(location);
|
||||
}
|
||||
|
||||
private static class FinalMethodVisitor extends BaseInspectionVisitor {
|
||||
private FinalMethodVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!method.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.FINAL, method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RemoveModifierFix;
|
||||
|
||||
public class FinalPrivateMethodInspection extends MethodInspection {
|
||||
public String getDisplayName() {
|
||||
return "'private' method declared 'final'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'private' method declared '#ref' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FinalStaticMethodVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return new RemoveModifierFix(location);
|
||||
}
|
||||
|
||||
private static class FinalStaticMethodVisitor extends BaseInspectionVisitor {
|
||||
private FinalStaticMethodVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!method.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| !method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.FINAL, method);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RemoveModifierFix;
|
||||
|
||||
public class FinalStaticMethodInspection extends MethodInspection {
|
||||
public String getDisplayName() {
|
||||
return "'static' method declared 'final'";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "'static' method declared '#ref' #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new FinalStaticMethodVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return new RemoveModifierFix(location);
|
||||
}
|
||||
|
||||
private static class FinalStaticMethodVisitor extends BaseInspectionVisitor {
|
||||
private FinalStaticMethodVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!method.hasModifierProperty(PsiModifier.FINAL)
|
||||
|| !method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.FINAL, method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.MoveClassFix;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
|
||||
public class InnerClassOnInterfaceInspection extends ClassInspection {
|
||||
private final MoveClassFix fix = new MoveClassFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Inner class of interface";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
final PsiClass innerClass = (PsiClass) location.getParent();
|
||||
final PsiClass parentInterface =
|
||||
ClassUtils.getContainingClass(innerClass);
|
||||
final String interfaceName = parentInterface.getName();
|
||||
return "Interface " + interfaceName + " has inner class #ref #loc";
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new InnerClassOnInterfaceVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class InnerClassOnInterfaceVisitor extends BaseInspectionVisitor {
|
||||
private InnerClassOnInterfaceVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (!aClass.isInterface()||aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
final PsiClass[] innerClasses = aClass.getInnerClasses();
|
||||
for (int i = 0; i < innerClasses.length; i++) {
|
||||
registerClassError(innerClasses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class LimitedScopeInnerClassInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Limited-scope class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Limited-scope inner class #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new LimitedScopeInnerClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class LimitedScopeInnerClassVisitor extends BaseInspectionVisitor {
|
||||
private LimitedScopeInnerClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
if (aClass.getParent() instanceof PsiDeclarationStatement) {
|
||||
registerClassError(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.ClassInspection;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
|
||||
public class MarkerInterfaceInspection extends ClassInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Marker interface";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Marker interface #ref #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MarkerInterfaceVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MarkerInterfaceVisitor extends BaseInspectionVisitor {
|
||||
private MarkerInterfaceVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (!aClass.isInterface() || aClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
final PsiField[] fields = aClass.getFields();
|
||||
if (fields.length != 0) {
|
||||
return;
|
||||
}
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
if (methods.length != 0) {
|
||||
return;
|
||||
}
|
||||
final PsiClassType[] extendsList = aClass.getExtendsListTypes();
|
||||
if (extendsList.length > 1) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.MoveClassFix;
|
||||
|
||||
public class MultipleTopLevelClassesInFileInspection extends ClassInspection {
|
||||
private final MoveClassFix fix = new MoveClassFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Multiple top level classes in single file";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Multiple top level classes in file";
|
||||
}
|
||||
|
||||
protected InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new MultipleTopLevelClassesInFileVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class MultipleTopLevelClassesInFileVisitor extends BaseInspectionVisitor {
|
||||
|
||||
private MultipleTopLevelClassesInFileVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitClass(PsiClass aClass) {
|
||||
// no call to super, so that it doesn't drill down to inner classes
|
||||
if (!(aClass.getParent() instanceof PsiJavaFile)) {
|
||||
return;
|
||||
}
|
||||
int numClasses = 0;
|
||||
final PsiJavaFile file = (PsiJavaFile) aClass.getParent();
|
||||
final PsiElement[] children = file.getChildren();
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
final PsiElement child = children[i];
|
||||
if (child instanceof PsiClass) {
|
||||
numClasses++;
|
||||
}
|
||||
}
|
||||
if (numClasses <= 1) {
|
||||
return;
|
||||
}
|
||||
registerClassError(aClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.ui.SingleCheckboxOptionsPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class NonProtectedConstructorInAbstractClassInspection extends MethodInspection {
|
||||
public boolean m_ignoreNonPublicClasses = false;
|
||||
private static final Logger s_logger =
|
||||
Logger.getInstance("NonProtectedConstructorInAbstractClassInspection");
|
||||
private final MakeProtectedFix fix = new MakeProtectedFix();
|
||||
|
||||
public String getDisplayName() {
|
||||
return "Constructor not 'protected' in 'abstract' class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Constructor '#ref' is not declared 'protected' in 'abstract' class #loc";
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel("Ignore for non-public classes",
|
||||
this, "m_ignoreNonPublicClasses");
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new NonProtectedConstructorInAbstractClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return fix;
|
||||
}
|
||||
|
||||
private static class MakeProtectedFix extends InspectionGadgetsFix {
|
||||
public String getName() {
|
||||
return "Make 'protected'";
|
||||
}
|
||||
|
||||
public void applyFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement constructorIdentifier = descriptor.getPsiElement();
|
||||
try {
|
||||
final PsiMethod constructor = (PsiMethod) constructorIdentifier.getParent();
|
||||
final PsiModifierList modifiers = constructor.getModifierList();
|
||||
modifiers.setModifierProperty(PsiModifier.PUBLIC, false);
|
||||
modifiers.setModifierProperty(PsiModifier.PRIVATE, false);
|
||||
modifiers.setModifierProperty(PsiModifier.PROTECTED, true);
|
||||
} catch (IncorrectOperationException e) {
|
||||
s_logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class NonProtectedConstructorInAbstractClassVisitor extends BaseInspectionVisitor {
|
||||
private NonProtectedConstructorInAbstractClassVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!method.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
if (method.hasModifierProperty(PsiModifier.PROTECTED)
|
||||
|| method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (m_ignoreNonPublicClasses && !containingClass.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
if (containingClass.isEnum()) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.GroupNames;
|
||||
import com.siyeh.ig.MethodInspection;
|
||||
|
||||
public class NoopMethodInAbstractClassInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "No-op method in abstract class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "No-op Method '#ref' should be made abstract #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new NoopMethodInAbstractClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
private static class NoopMethodInAbstractClassVisitor extends BaseInspectionVisitor {
|
||||
private NoopMethodInAbstractClassVisitor(BaseInspection inspection,
|
||||
InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (method.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass.isInterface() || containingClass.isAnnotationType()) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
return;
|
||||
}
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
final PsiStatement[] statements = body.getStatements();
|
||||
if (statements == null) {
|
||||
return;
|
||||
}
|
||||
if (statements.length > 0) {
|
||||
return;
|
||||
}
|
||||
registerMethodError(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.siyeh.ig.classlayout;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiSuperMethodUtil;
|
||||
import com.siyeh.ig.*;
|
||||
import com.siyeh.ig.fixes.RemoveModifierFix;
|
||||
|
||||
public class ProtectedMemberInFinalClassInspection extends MethodInspection {
|
||||
|
||||
public String getDisplayName() {
|
||||
return "'protected' member in 'final' class";
|
||||
}
|
||||
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.CLASSLAYOUT_GROUP_NAME;
|
||||
}
|
||||
|
||||
public String buildErrorString(PsiElement location) {
|
||||
return "Class member declared '#ref' in 'final' class #loc";
|
||||
}
|
||||
|
||||
public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
|
||||
return new ProtectedMemberInFinalClassVisitor(this, inspectionManager, onTheFly);
|
||||
}
|
||||
|
||||
public InspectionGadgetsFix buildFix(PsiElement location) {
|
||||
return new RemoveModifierFix(location);
|
||||
}
|
||||
|
||||
private static class ProtectedMemberInFinalClassVisitor extends BaseInspectionVisitor {
|
||||
private ProtectedMemberInFinalClassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
|
||||
super(inspection, inspectionManager, isOnTheFly);
|
||||
}
|
||||
|
||||
public void visitMethod(PsiMethod method) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!method.hasModifierProperty(PsiModifier.PROTECTED)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
if (methodOverrides(method)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.PROTECTED, method);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static boolean methodOverrides(PsiMethod meth) {
|
||||
final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(meth);
|
||||
return superMethods != null && superMethods.length != 0;
|
||||
}
|
||||
|
||||
public void visitField(PsiField field) {
|
||||
//no call to super, so we don't drill into anonymous classes
|
||||
if (!field.hasModifierProperty(PsiModifier.PROTECTED)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = field.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
if (!containingClass.hasModifierProperty(PsiModifier.FINAL)) {
|
||||
return;
|
||||
}
|
||||
registerModifierError(PsiModifier.PROTECTED, field);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user