This commit is contained in:
Olesya Smirnova
2004-11-05 20:15:51 +03:00
commit 3dbff843ac
1382 changed files with 63873 additions and 0 deletions

View 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(*)

View 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>

View 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 &quot;1.4.2_05&quot;" />
<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 &quot;1.5.0-beta2&quot;" />
<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>

View 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="&quot;" />
</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>

View 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>

View 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>

View 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>

View File

@@ -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;
}
}

View File

@@ -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]);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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>

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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");
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}
}
}
}

View File

@@ -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;
}
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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]);
}
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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