diff --git a/plugins/InspectionGadgets/Leftovers.txt b/plugins/InspectionGadgets/Leftovers.txt
new file mode 100644
index 000000000000..286e3def5594
--- /dev/null
+++ b/plugins/InspectionGadgets/Leftovers.txt
@@ -0,0 +1,22 @@
+ Query string should be constant
+ Reuse of local variable.
+ Logging not wrapped in if block
+ Public method without logging
+ Logger constructed without the current class name as argument.
+ Class initialization circularity
+ Incorrect lazy initialization of static field
+ setter or getter with non-standard name
+ Avoid repeated casting
+ arithmetic operations on volatile types
+ Field has setter but no getter
+ Name with forbidden component
+ Paired open/close for Sockets
+ Paired open/close for Channels
+ Paired acquire/release for Locks
+
+ Inheritance as type def (change the EmptyClass inspection)
+ changing multiply/divide to shift may change precedence!
+ Fix the "variable accessed in synchronized and unsynchronized contexts" to deal
+ with unsynchronized private methods called only from synchronized contexts
+ SerialVersionUID calculation
+
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/InstanceofChainInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/InstanceofChainInspection.java
new file mode 100644
index 000000000000..52d953afbdd1
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/InstanceofChainInspection.java
@@ -0,0 +1,89 @@
+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.StatementInspection;
+
+public class InstanceofChainInspection extends StatementInspection {
+
+ public String getDisplayName() {
+ return "Chain of 'instanceof' checks";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.ABSTRACTION_GROUP_NAME;
+ }
+
+ protected String buildErrorString(PsiElement location) {
+ return "Chain of 'instanceof' checks indicates abstraction faiulre #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new InstanceofChainVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class InstanceofChainVisitor extends BaseInspectionVisitor {
+ private InstanceofChainVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitIfStatement(PsiIfStatement statement) {
+ super.visitIfStatement(statement);
+ final PsiElement parent = statement.getParent();
+ if (parent instanceof PsiIfStatement) {
+ final PsiIfStatement parentStatement = (PsiIfStatement) parent;
+ final PsiStatement elseBranch = parentStatement.getElseBranch();
+ if (statement.equals(elseBranch)) {
+ return;
+ }
+ }
+ int numChecks = 0;
+ PsiIfStatement branch = statement;
+ while (branch != null) {
+ final PsiExpression condition = branch.getCondition();
+ if (!isInstanceofCheck(condition)) {
+ return;
+ }
+ numChecks++;
+
+ final PsiStatement elseBranch = branch.getElseBranch();
+ if (elseBranch instanceof PsiIfStatement) {
+ branch = (PsiIfStatement) elseBranch;
+ } else {
+ branch = null;
+ }
+ }
+ if (numChecks < 2) {
+ return;
+ }
+ registerStatementError(statement);
+ }
+
+ private boolean isInstanceofCheck(PsiExpression condition) {
+ if (condition == null) {
+ return false;
+ } else if (condition instanceof PsiInstanceOfExpression) {
+ return true;
+ } else if (condition instanceof PsiBinaryExpression) {
+ final PsiBinaryExpression binaryExpression = (PsiBinaryExpression) condition;
+ final PsiExpression lhs = binaryExpression.getLOperand();
+ final PsiExpression rhs = binaryExpression.getROperand();
+ return isInstanceofCheck(lhs) && isInstanceofCheck(rhs);
+ } else if (condition instanceof PsiParenthesizedExpression) {
+ final PsiExpression contents = ((PsiParenthesizedExpression) condition).getExpression();
+ return isInstanceofCheck(contents);
+ } else if (condition instanceof PsiPrefixExpression) {
+ final PsiExpression contents = ((PsiPrefixExpression) condition).getOperand();
+ return isInstanceofCheck(contents);
+ } else if (condition instanceof PsiPostfixExpression) {
+ final PsiExpression contents = ((PsiPostfixExpression) condition).getOperand();
+ return isInstanceofCheck(contents);
+ }
+ return false;
+ }
+
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
new file mode 100644
index 000000000000..a82e3cd49081
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
@@ -0,0 +1,92 @@
+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 StaticCallOnSubclassInspection extends ExpressionInspection {
+ private final StaticCallOnSubclassFix fix = new StaticCallOnSubclassFix();
+
+
+ public String getDisplayName() {
+ return "Static method referenced via subclass";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.BUGS_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiMethodCallExpression methodCall = (PsiMethodCallExpression) location.getParent().getParent();
+ final PsiMethod method = methodCall.resolveMethod();
+ final String declaringClass = method.getContainingClass().getName();
+ final String referencedClass = methodCall.getMethodExpression().getQualifier().getText();
+ return "Static method '#ref' declared on class " + declaringClass + " but referenced via class" + referencedClass + " #loc";
+ }
+
+ protected InspectionGadgetsFix buildFix(PsiElement location) {
+ return fix;
+ }
+
+ private static class StaticCallOnSubclassFix extends InspectionGadgetsFix {
+ public String getName() {
+ return "Rationalize static method call";
+ }
+
+ public void applyFix(Project project, ProblemDescriptor descriptor) {
+ final PsiIdentifier name = (PsiIdentifier) descriptor.getPsiElement();
+ final PsiReferenceExpression expression = (PsiReferenceExpression) name.getParent();
+ final PsiMethodCallExpression call = (PsiMethodCallExpression) expression.getParent();
+ final PsiMethod method = call.resolveMethod();
+ final String methodName = expression.getReferenceName();
+ final PsiClass containingClass = method.getContainingClass();
+ final PsiExpressionList argumentList = call.getArgumentList();
+ final PsiExpression[] args = argumentList.getExpressions();
+ final String argText = args[0].getText();
+ replaceExpression(project, call, containingClass.getName() + '.' + methodName + "(" + argText + ")");
+ }
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new StaticCallOnSubclassVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class StaticCallOnSubclassVisitor extends BaseInspectionVisitor {
+ private StaticCallOnSubclassVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethodCallExpression(PsiMethodCallExpression call) {
+ super.visitMethodCallExpression(call);
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
+ if (methodExpression == null) {
+ return;
+ }
+ final PsiElement qualifier = methodExpression.getQualifier();
+ if (!(qualifier instanceof PsiReferenceExpression)) {
+ return;
+ }
+ final PsiElement referent = ((PsiReference) qualifier).resolve();
+ if (!(referent instanceof PsiClass)) {
+ return;
+ }
+ final PsiClass referencedClass = (PsiClass) referent;
+ final PsiMethod method = call.resolveMethod();
+ if (method == null) {
+ return;
+ }
+
+ final PsiClass declaringClass = method.getContainingClass();
+ if (declaringClass.equals(referencedClass)) {
+ return;
+ }
+ registerMethodCallError(call);
+
+ }
+
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/UseOfAnotherObjectsPrivateFieldInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/UseOfAnotherObjectsPrivateFieldInspection.java
new file mode 100644
index 000000000000..3d0e376801a2
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/UseOfAnotherObjectsPrivateFieldInspection.java
@@ -0,0 +1,61 @@
+package com.siyeh.ig.encapsulation;
+
+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 UseOfAnotherObjectsPrivateFieldInspection extends ExpressionInspection {
+
+ public String getDisplayName() {
+ return "Accessing a non-public field of another object";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.ENCAPSULATION_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Direct access of non-public field #ref on another object #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new UseOfAnotherObjectsPrivateFieldVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class UseOfAnotherObjectsPrivateFieldVisitor extends BaseInspectionVisitor {
+ private UseOfAnotherObjectsPrivateFieldVisitor(BaseInspection inspection,
+ InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
+ final PsiExpression qualifier = expression.getQualifierExpression();
+ if(qualifier == null || qualifier instanceof PsiThisExpression)
+ {
+ return;
+ }
+ final PsiElement referent = expression.resolve();
+ if(referent == null)
+ {
+ return;
+ }
+ if(!(referent instanceof PsiField))
+ {
+ return;
+ }
+ final PsiField field = (PsiField)referent;
+ if(!field.hasModifierProperty(PsiModifier.PRIVATE) &&
+ !field.hasModifierProperty(PsiModifier.PROTECTED))
+ {
+ return;
+ }
+ final PsiElement fieldNameElement = expression.getReferenceNameElement();
+ registerError(fieldNameElement);
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionCaught.form b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionCaught.form
new file mode 100644
index 000000000000..c4ce2ade728a
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionCaught.form
@@ -0,0 +1,46 @@
+
+
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionCaughtInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionCaughtInspection.java
new file mode 100644
index 000000000000..ed016cef39e5
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionCaughtInspection.java
@@ -0,0 +1,201 @@
+package com.siyeh.ig.errorhandling;
+
+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 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;
+
+public class BadExceptionCaughtInspection extends ExpressionInspection {
+ public String exceptionCheckString =
+ "java.lang.NullPointerException," +
+ "java.lang.IllegalMonitorStateException," +
+ "java.lang.ArrayOutOfBoundsException";
+
+ private List exceptionsList = new ArrayList(32);
+
+ {
+ parseExceptionsString();
+ }
+
+ public void readSettings(Element element) throws InvalidDataException {
+ super.readSettings(element);
+ parseExceptionsString();
+ }
+
+ private void parseExceptionsString() {
+ exceptionsList.clear();
+ final String[] strings = exceptionCheckString.split(",");
+ for (int i = 0; i < strings.length; i++ ) {
+ exceptionsList.add(strings[i]);
+ }
+ }
+
+ 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 = exceptionsList.iterator(); iterator.hasNext();) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(',');
+ }
+ final String exceptionName = (String) iterator.next();
+ buffer.append(exceptionName);
+ }
+ exceptionCheckString = buffer.toString();
+ }
+
+ public String getDisplayName() {
+ return "Prohibitted exception caught";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.ERRORHANDLING_GROUP_NAME;
+ }
+
+ public JComponent createOptionsPanel() {
+ final Form form = new Form();
+ return form.getContentPanel();
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Prohibitted exception '#ref' caught. #loc ";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new BadExceptionCaughtVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private class BadExceptionCaughtVisitor extends BaseInspectionVisitor {
+ private BadExceptionCaughtVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitTryStatement(PsiTryStatement statement) {
+
+ super.visitTryStatement(statement);
+ final PsiParameter[] catchBlockParameters = statement.getCatchBlockParameters();
+ for (int i = 0; i < catchBlockParameters.length; i++) {
+ final PsiParameter parameter = catchBlockParameters[i];
+ if(parameter == null)
+ {
+ continue;
+ }
+ final PsiType type = parameter.getType();
+ if(type == null)
+ {
+ continue;
+ }
+ final String text = type.getCanonicalText();
+ if(text == null)
+ {
+ continue;
+ }
+ for (Iterator iterator = exceptionsList.iterator(); iterator.hasNext();) {
+ final String exceptionClass = (String) iterator.next();
+ if (text.equals(exceptionClass)) {
+ final PsiTypeElement typeElement = parameter.getTypeElement();
+ registerError(typeElement);
+ continue;
+ }
+ }
+ }
+
+ }
+
+
+ }
+
+ 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) {
+ exceptionsList.add("");
+ 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--) {
+ exceptionsList.remove(selectedRows[i]);
+ }
+ model.fireTableStructureChanged();
+ }
+ });
+ }
+
+ public JComponent getContentPanel() {
+ return contentPanel;
+ }
+ }
+
+ private class ReturnCheckSpecificationTableModel extends AbstractTableModel {
+
+ public int getRowCount() {
+ return exceptionsList.size();
+ }
+
+ public int getColumnCount() {
+ return 1;
+ }
+
+ public String getColumnName(int columnIndex) {
+ return "Exception class";
+ }
+
+ public Class getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return true;
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return exceptionsList.get(rowIndex);
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ exceptionsList.set(rowIndex, aValue);
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclared.form b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclared.form
new file mode 100644
index 000000000000..0d8cc37735d4
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclared.form
@@ -0,0 +1,46 @@
+
+
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
new file mode 100644
index 000000000000..696b87527a18
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
@@ -0,0 +1,201 @@
+package com.siyeh.ig.errorhandling;
+
+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.*;
+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;
+
+public class BadExceptionDeclaredInspection extends MethodInspection {
+ public String exceptionCheckString = "java.lang.Throwable," +
+ "java.lang.Exception," +
+ "java.lang.Error," +
+ "java.lang.RuntimeException," +
+ "java.lang.NullPointerException," +
+ "java.lang.ClassCastException," +
+ "java.lang.ArrayOutOfBoundsException";
+
+ private List exceptionsList = new ArrayList(32);
+
+ {
+ parseCallCheckString();
+ }
+
+ public void readSettings(Element element) throws InvalidDataException {
+ super.readSettings(element);
+ parseCallCheckString();
+ }
+
+ private void parseCallCheckString() {
+ exceptionsList.clear();
+ final String[] strings = exceptionCheckString.split(",");
+ for (int i = 0; i < strings.length; i++ ) {
+ exceptionsList.add(strings[i]);
+ }
+ }
+
+ 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 = exceptionsList.iterator(); iterator.hasNext();) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(',');
+ }
+ final String exceptionName = (String) iterator.next();
+ buffer.append(exceptionName);
+ }
+ exceptionCheckString = buffer.toString();
+ }
+
+ public String getDisplayName() {
+ return "Prohibitted exception declared";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.ERRORHANDLING_GROUP_NAME;
+ }
+
+ public JComponent createOptionsPanel() {
+ final Form form = new Form();
+ return form.getContentPanel();
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiThrowStatement throwStatement = (PsiThrowStatement) location.getParent();
+ final PsiExpression exception = throwStatement.getException();
+ final PsiType type = exception.getType();
+ final String exceptionName = type.getPresentableText();
+ return "Prohibitted exception '" + exceptionName + "' declared. #loc ";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new BadExceptionDeclaredVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private class BadExceptionDeclaredVisitor extends BaseInspectionVisitor {
+ private BadExceptionDeclaredVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethod(PsiMethod method) {
+ super.visitMethod(method);
+ final PsiReferenceList throwsList = method.getThrowsList();
+ if(throwsList ==null)
+ {
+ return;
+ }
+ final PsiJavaCodeReferenceElement[] references =
+ throwsList.getReferenceElements();
+ if(references == null)
+ {
+ return;
+ }
+ for (int i = 0; i < references.length; i++) {
+ final PsiClass thrownClass = (PsiClass) references[i].resolve();
+ if(thrownClass != null)
+ {
+ final String text = thrownClass.getQualifiedName();
+ for (Iterator iterator = exceptionsList.iterator(); iterator.hasNext();) {
+ final String exceptionClass = (String) iterator.next();
+ if (text.equals(exceptionClass)) {
+ registerError(references[i]);
+ continue;
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ 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) {
+ exceptionsList.add("");
+ 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--) {
+ exceptionsList.remove(selectedRows[i]);
+ }
+ model.fireTableStructureChanged();
+ }
+ });
+ }
+
+ public JComponent getContentPanel() {
+ return contentPanel;
+ }
+ }
+
+ private class ReturnCheckSpecificationTableModel extends AbstractTableModel {
+
+ public int getRowCount() {
+ return exceptionsList.size();
+ }
+
+ public int getColumnCount() {
+ return 1;
+ }
+
+ public String getColumnName(int columnIndex) {
+ return "Exception class";
+ }
+
+ public Class getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return true;
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return exceptionsList.get(rowIndex);
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ exceptionsList.set(rowIndex, aValue);
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionThrown.form b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionThrown.form
new file mode 100644
index 000000000000..d2f4bf33b5f1
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionThrown.form
@@ -0,0 +1,46 @@
+
+
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionThrownInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionThrownInspection.java
new file mode 100644
index 000000000000..d9f90cb288e1
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionThrownInspection.java
@@ -0,0 +1,198 @@
+package com.siyeh.ig.errorhandling;
+
+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 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;
+
+public class BadExceptionThrownInspection extends ExpressionInspection {
+ public String exceptionCheckString = "java.lang.Throwable," +
+ "java.lang.Exception," +
+ "java.lang.Error," +
+ "java.lang.RuntimeException," +
+ "java.lang.NullPointerException," +
+ "java.lang.ClassCastException," +
+ "java.lang.ArrayOutOfBoundsException";
+
+ private List exceptionsList = new ArrayList(32);
+
+ {
+ parseCallCheckString();
+ }
+
+ public void readSettings(Element element) throws InvalidDataException {
+ super.readSettings(element);
+ parseCallCheckString();
+ }
+
+ private void parseCallCheckString() {
+ exceptionsList.clear();
+ final String[] strings = exceptionCheckString.split(",");
+ for (int i = 0; i < strings.length; i++ ) {
+ exceptionsList.add(strings[i]);
+ }
+ }
+
+ 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 = exceptionsList.iterator(); iterator.hasNext();) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.append(',');
+ }
+ final String exceptionName = (String) iterator.next();
+ buffer.append(exceptionName);
+ }
+ exceptionCheckString = buffer.toString();
+ }
+
+ public String getDisplayName() {
+ return "Prohibitted exception thrown";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.ERRORHANDLING_GROUP_NAME;
+ }
+
+ public JComponent createOptionsPanel() {
+ final Form form = new Form();
+ return form.getContentPanel();
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiThrowStatement throwStatement = (PsiThrowStatement) location.getParent();
+ final PsiExpression exception = throwStatement.getException();
+ final PsiType type = exception.getType();
+ final String exceptionName = type.getPresentableText();
+ return "Prohibitted exception '" + exceptionName + "' thrown. #loc ";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new BadExceptionThrownVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private class BadExceptionThrownVisitor extends BaseInspectionVisitor {
+ private BadExceptionThrownVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitThrowStatement(PsiThrowStatement statement) {
+ super.visitThrowStatement(statement);
+ final PsiExpression exception = statement.getException();
+ if(exception == null)
+ {
+ return;
+ }
+ final PsiType type = exception.getType();
+ if(type == null)
+ {
+ return;
+ }
+ final String text = type.getCanonicalText();
+ for (Iterator iterator = exceptionsList.iterator(); iterator.hasNext();) {
+ final String exceptionClass = (String) iterator.next();
+ if(text.equals(exceptionClass))
+ {
+ registerStatementError(statement);
+ return;
+ }
+ }
+ }
+
+ }
+
+ 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) {
+ exceptionsList.add("");
+ 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--) {
+ exceptionsList.remove(selectedRows[i]);
+ }
+ model.fireTableStructureChanged();
+ }
+ });
+ }
+
+ public JComponent getContentPanel() {
+ return contentPanel;
+ }
+ }
+
+ private class ReturnCheckSpecificationTableModel extends AbstractTableModel {
+
+ public int getRowCount() {
+ return exceptionsList.size();
+ }
+
+ public int getColumnCount() {
+ return 1;
+ }
+
+ public String getColumnName(int columnIndex) {
+ return "Exception class";
+ }
+
+ public Class getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return true;
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return exceptionsList.get(rowIndex);
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ exceptionsList.set(rowIndex, aValue);
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java
new file mode 100644
index 000000000000..0e81e8f985e3
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/InlineVariableFix.java
@@ -0,0 +1,25 @@
+package com.siyeh.ig.fixes;
+
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLocalVariable;
+import com.intellij.refactoring.RefactoringActionHandler;
+import com.intellij.refactoring.RefactoringActionHandlerFactory;
+import com.siyeh.ig.InspectionGadgetsFix;
+
+public class InlineVariableFix extends InspectionGadgetsFix {
+
+ public String getName() {
+ return "Inline variable";
+ }
+
+ public void applyFix(Project project, ProblemDescriptor problemDescriptor) {
+ final PsiElement nameElement = problemDescriptor.getPsiElement();
+ final PsiLocalVariable variable = (PsiLocalVariable) nameElement.getParent();
+ final RefactoringActionHandlerFactory factory =
+ RefactoringActionHandlerFactory.getInstance();
+ final RefactoringActionHandler inlineHandler = factory.createInlineHandler();
+ inlineHandler.invoke(project, new PsiElement[]{variable}, null);
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.java
new file mode 100644
index 000000000000..2d75b07bad0f
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.java
@@ -0,0 +1,61 @@
+package com.siyeh.ig.internationalization;
+
+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 SimpleDateFormatWithoutLocaleInspection extends ExpressionInspection {
+
+ public String getDisplayName() {
+ return "Instantiating a SimpleDateFormat without a Locale";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.INTERNATIONALIZATION_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Instantiating a #ref without specifying a Locale in an internationalized context #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new SimpleDateFormatWithoutLocaleVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class SimpleDateFormatWithoutLocaleVisitor extends BaseInspectionVisitor {
+ private SimpleDateFormatWithoutLocaleVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitNewExpression(PsiNewExpression expression) {
+ super.visitNewExpression(expression);
+ if(!TypeUtils.expressionHasType("java.util.SimpleDateFormat", expression))
+ {
+ return;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ if(argumentList == null)
+ {
+ return;
+ }
+ final PsiExpression[] args = argumentList.getExpressions();
+ if(args == null)
+ {
+ return;
+ }
+ for (int i = 0; i < args.length; i++) {
+ if(TypeUtils.expressionHasType("java.util.Locale", args[i]))
+ {
+ return;
+ }
+ }
+ final PsiJavaCodeReferenceElement classReference = expression.getClassReference();
+ registerError(classReference);
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
new file mode 100644
index 000000000000..f284c546e5c9
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
@@ -0,0 +1,152 @@
+package com.siyeh.ig.junit;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.siyeh.ig.*;
+import com.siyeh.ig.psiutils.ClassUtils;
+
+public class MisorderedAssertEqualsParametersInspection extends ExpressionInspection {
+ private FlipParametersFix fix = new FlipParametersFix();
+
+
+ public String getDisplayName() {
+ return "Misordered assertEquals parameters";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.JUNIT_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Parameters to #ref() in wrong order #loc";
+ }
+
+ public InspectionGadgetsFix buildFix(PsiElement location) {
+ return fix;
+ }
+
+ private static class FlipParametersFix extends InspectionGadgetsFix {
+ public String getName() {
+ return "Flip compared parameters";
+ }
+
+ public void applyFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement methodNameIdentifier = descriptor.getPsiElement();
+ final PsiMethodCallExpression callExpression = (PsiMethodCallExpression) methodNameIdentifier.getParent().getParent();
+ final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
+
+ final PsiMethod method = (PsiMethod) methodExpression.resolve();
+ final PsiParameterList paramList = method.getParameterList();
+ final PsiParameter[] parameters = paramList.getParameters();
+ final PsiManager psiManager = callExpression.getManager();
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ final PsiType stringType = PsiType.getJavaLangString(psiManager, scope);
+ final PsiType paramType1 = parameters[0].getType();
+ final int expectedPosition;
+ final int actualPosition;
+ if (paramType1.equals(stringType) && parameters.length > 2) {
+ expectedPosition = 1;
+ actualPosition = 2;
+ } else {
+ expectedPosition = 0;
+ actualPosition = 1;
+ }
+ final PsiExpressionList argumentList = callExpression.getArgumentList();
+
+ final PsiExpression[] args = argumentList.getExpressions();
+ final PsiExpression expectedArg = args[expectedPosition];
+ final PsiExpression actualArg = args[actualPosition];
+ final String actualArgText = actualArg.getText();
+ final String expectedArgText = expectedArg.getText();
+ replaceExpression(project, expectedArg, actualArgText);
+ replaceExpression(project, actualArg, expectedArgText);
+ }
+
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new MisorderedAssertEqualsParametersVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class MisorderedAssertEqualsParametersVisitor extends BaseInspectionVisitor {
+
+ private MisorderedAssertEqualsParametersVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ if (!isAssertEquals(expression)) {
+ return;
+ }
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+
+ final PsiMethod method = (PsiMethod) methodExpression.resolve();
+ final PsiParameterList paramList = method.getParameterList();
+ if (paramList == null) {
+ return;
+ }
+ final PsiParameter[] parameters = paramList.getParameters();
+
+ final PsiManager psiManager = expression.getManager();
+
+ final Project project = psiManager.getProject();
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ final PsiType stringType = PsiType.getJavaLangString(psiManager, scope);
+ final PsiType paramType1 = parameters[0].getType();
+ final int expectedPosition;
+ final int actualPosition ;
+ if (paramType1.equals(stringType)&& parameters.length > 2) {
+ expectedPosition = 1;
+ actualPosition = 2;
+ } else {
+ expectedPosition = 0;
+ actualPosition = 1;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ if(argumentList == null)
+ {
+ return;
+ }
+ final PsiExpression[] args = argumentList.getExpressions();
+ final PsiExpression expectedArg = args[expectedPosition];
+ final PsiExpression actualArg = args[actualPosition];
+ if(expectedArg == null || actualArg == null)
+ {
+ return;
+ }
+ if(expectedArg instanceof PsiLiteralExpression)
+ {
+ return;
+ }
+ if (!(actualArg instanceof PsiLiteralExpression))
+ {
+ return;
+ }
+ registerMethodCallError(expression);
+ }
+
+ private static boolean isAssertEquals(PsiMethodCallExpression expression) {
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ final String methodName = methodExpression.getReferenceName();
+ if (!"assertEquals".equals(methodName)) {
+ return false;
+ }
+ final PsiMethod method = (PsiMethod) methodExpression.resolve();
+ if (method == null) {
+ return false;
+ }
+
+ final PsiClass targetClass = method.getContainingClass();
+ if (!ClassUtils.isSubclass(targetClass, "junit.framework.Assert")) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
new file mode 100644
index 000000000000..1a2c91c05ee8
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
@@ -0,0 +1,245 @@
+package com.siyeh.ig.junit;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.siyeh.ig.*;
+import com.siyeh.ig.psiutils.ClassUtils;
+
+public class SimplifiableJUnitAssertionInspection extends ExpressionInspection {
+ private SimplifyJUnitAssertFix fix = new SimplifyJUnitAssertFix();
+
+
+ public String getDisplayName() {
+ return "Simplifiable JUnit assertion";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.JUNIT_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "#ref() can be simplified to assertEquals() #loc";
+ }
+
+ public InspectionGadgetsFix buildFix(PsiElement location) {
+ return fix;
+ }
+
+ private static class SimplifyJUnitAssertFix extends InspectionGadgetsFix {
+ public String getName() {
+ return "Simplify assertion";
+ }
+
+ public void applyFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement methodNameIdentifier = descriptor.getPsiElement();
+ final PsiMethodCallExpression callExpression = (PsiMethodCallExpression) methodNameIdentifier.getParent().getParent();
+ final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
+
+ final PsiMethod method = (PsiMethod) methodExpression.resolve();
+ final PsiParameterList paramList = method.getParameterList();
+ final PsiParameter[] parameters = paramList.getParameters();
+
+ final PsiManager psiManager = callExpression.getManager();
+
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ final PsiType stringType = PsiType.getJavaLangString(psiManager, scope);
+ final PsiType paramType1 = parameters[0].getType();
+ final PsiExpressionList argumentList = callExpression.getArgumentList();
+
+ final PsiExpression[] args = argumentList.getExpressions();
+ final int testPosition;
+ final PsiExpression message;
+ if (paramType1.equals(stringType) && parameters.length > 2) {
+ testPosition = 1;
+ message = args[0];
+ } else {
+ testPosition = 0;
+ message = null;
+ }
+ final PsiExpression testArg = args[testPosition];
+
+ PsiExpression lhs = null;
+ PsiExpression rhs = null;
+ if (testArg instanceof PsiBinaryExpression) {
+ lhs = ((PsiBinaryExpression) testArg).getLOperand();
+ rhs = ((PsiBinaryExpression) testArg).getROperand();
+ } else if (testArg instanceof PsiMethodCallExpression) {
+ final PsiMethodCallExpression call = (PsiMethodCallExpression) testArg;
+ final PsiReferenceExpression equalityMethodExpression = call.getMethodExpression();
+ final PsiExpressionList equalityArgumentList = call.getArgumentList();
+ final PsiExpression[] equalityArgs = equalityArgumentList.getExpressions();
+ rhs = equalityArgs[0];
+ lhs = equalityMethodExpression.getQualifierExpression();
+ }
+ if(!(lhs instanceof PsiLiteralExpression) &&
+ rhs instanceof PsiLiteralExpression)
+ {
+ final PsiExpression temp = lhs;
+ lhs = rhs;
+ rhs = temp;
+ }
+ final StringBuffer newExpression = new StringBuffer("assertEquals(");
+ if(message!=null)
+ {
+ newExpression.append(message.getText());
+ newExpression.append(',');
+ }
+ newExpression.append(lhs.getText());
+ newExpression.append(',');
+ newExpression.append(rhs.getText());
+ if(isFloatingPoint(lhs) || isFloatingPoint(rhs))
+ {
+ newExpression.append(",0.0");
+ }
+ newExpression.append(')');
+ replaceExpression(project, callExpression, newExpression.toString());
+ }
+
+ private boolean isFloatingPoint(PsiExpression expression) {
+ final PsiType type = expression.getType();
+ return PsiType.FLOAT.equals(type)|| PsiType.DOUBLE.equals(type);
+ }
+
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new MisorderedAssertEqualsParametersVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class MisorderedAssertEqualsParametersVisitor extends BaseInspectionVisitor {
+
+ private MisorderedAssertEqualsParametersVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ if (!isAssertTrue(expression)) {
+ return;
+ }
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+
+ final PsiMethod method = (PsiMethod) methodExpression.resolve();
+ final PsiParameterList paramList = method.getParameterList();
+ if (paramList == null) {
+ return;
+ }
+ final PsiParameter[] parameters = paramList.getParameters();
+
+ final PsiManager psiManager = expression.getManager();
+
+ final Project project = psiManager.getProject();
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ final PsiType stringType = PsiType.getJavaLangString(psiManager, scope);
+ final PsiType paramType1 = parameters[0].getType();
+ final int testPosition;
+ if (paramType1.equals(stringType) && parameters.length > 1) {
+ testPosition = 1;
+ } else {
+ testPosition = 0;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ if (argumentList == null) {
+ return;
+ }
+ final PsiExpression[] args = argumentList.getExpressions();
+ final PsiExpression testArg = args[testPosition];
+ if (testArg == null) {
+ return;
+ }
+ if (!isEqualityComparison(testArg)) {
+ return;
+ }
+ registerMethodCallError(expression);
+ }
+
+ private boolean isEqualityComparison(PsiExpression testArg) {
+ if (testArg instanceof PsiBinaryExpression) {
+ final PsiJavaToken sign = ((PsiBinaryExpression) testArg).getOperationSign();
+ if(sign == null)
+ {
+ return false;
+ }
+ if(!sign.getTokenType().equals(JavaTokenType.EQEQ))
+ {
+ return false;
+ }
+ final PsiExpression lhs = ((PsiBinaryExpression) testArg).getLOperand();
+ if(lhs == null)
+ {
+ return false;
+ }
+ final PsiExpression rhs = ((PsiBinaryExpression) testArg).getROperand();
+ if(rhs == null)
+ {
+ return false;
+ }
+ final PsiType type = lhs.getType();
+ if(type == null)
+ {
+ return false;
+ }
+ if(!ClassUtils.isPrimitive(type))
+ {
+ return false;
+ }
+ return true;
+ } else if (testArg instanceof PsiMethodCallExpression) {
+ final PsiMethodCallExpression call = (PsiMethodCallExpression) testArg;
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
+ final String methodName = methodExpression.getReferenceName();
+ if(!"equals".equals(methodName))
+ {
+ return false;
+ }
+ final PsiExpressionList argumentList = call.getArgumentList();
+ if(argumentList == null)
+ {
+ return false;
+ }
+ final PsiExpression[] args = argumentList.getExpressions();
+ if(args == null)
+ {
+ return false;
+ }
+ if(args.length!=1)
+ {
+ return false;
+ }
+ if(args[0] == null)
+ {
+ return false;
+ }
+ if(methodExpression.getQualifierExpression() == null)
+ {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean isAssertTrue(PsiMethodCallExpression expression) {
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ final String methodName = methodExpression.getReferenceName();
+ if (!"assertTrue".equals(methodName)) {
+ return false;
+ }
+ final PsiMethod method = (PsiMethod) methodExpression.resolve();
+ if (method == null) {
+ return false;
+ }
+
+ final PsiClass targetClass = method.getContainingClass();
+ if (!ClassUtils.isSubclass(targetClass, "junit.framework.Assert")) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestCaseInProductCodeInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestCaseInProductCodeInspection.java
new file mode 100644
index 000000000000..8c361e227e54
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestCaseInProductCodeInspection.java
@@ -0,0 +1,54 @@
+package com.siyeh.ig.junit;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.psi.*;
+import com.siyeh.ig.psiutils.ClassUtils;
+import com.siyeh.ig.psiutils.TestUtils;
+import com.siyeh.ig.fixes.MoveClassFix;
+import com.siyeh.ig.*;
+
+public class TestCaseInProductCodeInspection extends ClassInspection {
+ private final MoveClassFix fix = new MoveClassFix();
+
+ public String getDisplayName() {
+ return "JUnit TestCase in product source";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.JUNIT_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Test case #ref should probably be placed in a test source tree #loc";
+ }
+
+ protected InspectionGadgetsFix buildFix(PsiElement location) {
+ return fix;
+ }
+
+ protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
+ return true;
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new TestCaseInProductCodeVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class TestCaseInProductCodeVisitor extends BaseInspectionVisitor {
+
+ private TestCaseInProductCodeVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitClass(PsiClass aClass) {
+ if (!ClassUtils.isSubclass(aClass, "junit.framework.TestCase")) {
+ return;
+ }
+ if(TestUtils.isTest(aClass))
+ {
+ return;
+ }
+ registerClassError(aClass);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UnconstructableTestCaseInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UnconstructableTestCaseInspection.java
new file mode 100644
index 000000000000..f76a540d9554
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/UnconstructableTestCaseInspection.java
@@ -0,0 +1,84 @@
+package com.siyeh.ig.junit;
+
+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;
+
+public class UnconstructableTestCaseInspection extends ClassInspection {
+
+ public String getDisplayName() {
+ return "Unconstructable JUnit TestCase";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.JUNIT_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Test case #ref is unusable by most test runners #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new UnconstructableTestCaseVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class UnconstructableTestCaseVisitor extends BaseInspectionVisitor {
+
+ private UnconstructableTestCaseVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitClass(PsiClass aClass) {
+ if (aClass.isInterface() || aClass.isEnum() || aClass.isAnnotationType() ||
+ aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ return;
+ }
+ if (!ClassUtils.isSubclass(aClass, "junit.framework.TestCase")) {
+ return;
+ }
+ boolean hasConstructor = false;
+ boolean hasNoArgConstructor = false;
+ boolean hasStringConstructor = false;
+
+ final PsiMethod[] constructors = aClass.getConstructors();
+ if (constructors == null) {
+ return;
+ }
+
+ for (int i = 0; i < constructors.length; i++) {
+ final PsiMethod constructor = constructors[i];
+ hasConstructor = true;
+ if (!constructor.hasModifierProperty(PsiModifier.PUBLIC)) {
+ continue;
+ }
+ final PsiParameterList parameterList = constructor.getParameterList();
+ final PsiParameter[] parameters = parameterList.getParameters();
+ if (parameters.length == 0) {
+ hasNoArgConstructor = true;
+ }
+ if (parameters.length == 1) {
+ final PsiType type = parameters[0].getType();
+ if (type != null) {
+ if (type.getCanonicalText().equals("java.lang.String")) {
+ hasStringConstructor = true;
+ }
+ }
+ }
+ }
+
+ if (!hasConstructor) {
+ return;
+ }
+ if (hasNoArgConstructor || hasStringConstructor) {
+ return;
+ }
+ registerClassError(aClass);
+ }
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/naming/ParameterNameDiffersFromOverriddenParameterInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/ParameterNameDiffersFromOverriddenParameterInspection.java
new file mode 100644
index 000000000000..98788b17f9da
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/ParameterNameDiffersFromOverriddenParameterInspection.java
@@ -0,0 +1,125 @@
+package com.siyeh.ig.naming;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import com.intellij.psi.PsiParameterList;
+import com.intellij.psi.util.PsiSuperMethodUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.*;
+import com.siyeh.ig.fixes.RenameFix;
+
+public class ParameterNameDiffersFromOverriddenParameterInspection extends MethodInspection {
+
+ public String getDisplayName() {
+ return "Parameter name differs from parameter in overridden method";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.NAMING_CONVENTIONS_GROUP_NAME;
+ }
+
+ protected InspectionGadgetsFix buildFix(PsiElement location) {
+ final PsiParameter parameter = (PsiParameter) location.getParent();
+ final String parameterName = parameter.getName();
+ final PsiMethod method = (PsiMethod) PsiTreeUtil.getParentOfType(parameter, PsiMethod.class);
+ final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
+ final int index = method.getParameterList().getParameterIndex(parameter);
+ String name = "";
+ for (int i = 0; i < superMethods.length; i++) {
+ final PsiMethod superMethod = superMethods[i];
+ final PsiParameterList parameterList = superMethod.getParameterList();
+ if (parameterList != null) {
+ final PsiParameter[] parameters = parameterList.getParameters();
+ if (parameters != null) {
+ final String superParameterName = parameters[index].getName();
+ if (superParameterName != null && !superParameterName.equals(parameterName)) {
+ name = superParameterName;
+ break;
+ }
+ }
+ }
+ }
+ return new RenameFix(name);
+ }
+
+ protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
+ return true;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiParameter parameter = (PsiParameter) location.getParent();
+ final String parameterName = parameter.getName();
+ final PsiMethod method = (PsiMethod) PsiTreeUtil.getParentOfType(parameter, PsiMethod.class);
+ final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
+ final int index = method.getParameterList().getParameterIndex(parameter);
+ String name = "";
+ for (int i = 0; i < superMethods.length; i++) {
+ final PsiMethod superMethod = superMethods[i];
+ final PsiParameterList parameterList = superMethod.getParameterList();
+ if (parameterList != null) {
+ final PsiParameter[] parameters = parameterList.getParameters();
+ if (parameters != null) {
+ final String superParameterName = parameters[index].getName();
+ if (superParameterName != null && !superParameterName.equals(parameterName)) {
+ name = superParameterName;
+ break;
+ }
+ }
+ }
+ }
+ return "Parameter name '#ref' is different from parameter '" + name + "'overridden #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new ParameterNameDiffersFromOverriddenParameterVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class ParameterNameDiffersFromOverriddenParameterVisitor extends BaseInspectionVisitor {
+ private ParameterNameDiffersFromOverriddenParameterVisitor(BaseInspection inspection,
+ InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethod(PsiMethod method) {
+ final PsiParameterList parameterList = method.getParameterList();
+ if (parameterList == null) {
+ return;
+ }
+ final PsiParameter[] parameters = parameterList.getParameters();
+ if (parameters == null || parameters.length == 0) {
+ return;
+ }
+ final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method);
+ if (superMethods == null || superMethods.length == 0) {
+ return;
+ }
+ for (int i = 0; i < parameters.length; i++) {
+ checkParameter(parameters[i], i, superMethods);
+ }
+ }
+
+ private void checkParameter(PsiParameter parameter, int index, PsiMethod[] superMethods) {
+ final String parameterName = parameter.getName();
+ if(parameterName == null)
+ {
+ return;
+ }
+ for (int i = 0; i < superMethods.length; i++) {
+ final PsiMethod superMethod = superMethods[i];
+ final PsiParameterList parameterList = superMethod.getParameterList();
+ if (parameterList != null) {
+ final PsiParameter[] parameters = parameterList.getParameters();
+ if (parameters != null) {
+ final String superParameterName = parameters[index].getName();
+ if (superParameterName!=null &&!superParameterName.equals(parameterName)) {
+ registerVariableError(parameter);
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferFieldInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferFieldInspection.java
new file mode 100644
index 000000000000..2748a3846848
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferFieldInspection.java
@@ -0,0 +1,56 @@
+package com.siyeh.ig.performance;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiField;
+import com.intellij.psi.PsiType;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.FieldInspection;
+import com.siyeh.ig.GroupNames;
+
+public class StringBufferFieldInspection extends FieldInspection {
+
+ public String getDisplayName() {
+ return "StringBuffer field";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.PERFORMANCE_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiField field = (PsiField) location.getParent();
+ final PsiType type = field.getType();
+ final String typeName = type.getPresentableText();
+ return typeName+ " field '#ref' #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new StringBufferFieldVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class StringBufferFieldVisitor extends BaseInspectionVisitor {
+ private StringBufferFieldVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitField(PsiField field) {
+ super.visitField(field);
+ final PsiType type = field.getType();
+ if(type == null)
+ {
+ return;
+ }
+ final String text = type.getCanonicalText();
+ if (!"java.lang.StringBuffer".equals(text) &&
+ !"java.lang.StringBuilder".equals(text)) {
+ return;
+ }
+ registerFieldError(field);
+
+ }
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TestUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TestUtils.java
new file mode 100644
index 000000000000..5e35162705c7
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TestUtils.java
@@ -0,0 +1,46 @@
+package com.siyeh.ig.psiutils;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.ProjectFileIndex;
+
+public class TestUtils {
+ private TestUtils() {
+ super();
+ }
+
+ public static boolean isTest(PsiClass aClass) {
+ final PsiManager manager = aClass.getManager();
+ final PsiFile file = (PsiFile) PsiTreeUtil.getParentOfType(aClass,
+ PsiFile.class);
+ final VirtualFile virtualFile = file.getVirtualFile();
+ final Project project = manager.getProject();
+ return TestUtils.isTest(project, virtualFile);
+ }
+
+ public static boolean isTest(PsiDirectory directory) {
+ final PsiManager manager = directory.getManager();
+ final VirtualFile virtualFile = directory.getVirtualFile();
+ final Project project = manager.getProject();
+ return TestUtils.isTest(project, virtualFile);
+ }
+
+ public static boolean isTest(Project project, VirtualFile virtualFile) {
+ if (virtualFile == null) {
+ return false;
+ }
+ final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
+ final ProjectFileIndex fileIndex = rootManager.getFileIndex();
+ return fileIndex.isInTestSourceContent(virtualFile);
+ }
+
+ public static boolean isTest(PsiJavaFile file) {
+ final PsiManager manager = file.getManager();
+ final VirtualFile virtualFile = file.getVirtualFile();
+ final Project project = manager.getProject();
+ return TestUtils.isTest(project, virtualFile);
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableUsedVisitor.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableUsedVisitor.java
new file mode 100644
index 000000000000..ec762cd402ec
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableUsedVisitor.java
@@ -0,0 +1,35 @@
+package com.siyeh.ig.psiutils;
+
+import com.intellij.psi.*;
+
+public class VariableUsedVisitor extends PsiRecursiveElementVisitor {
+ private boolean used = false;
+ private final PsiVariable variable;
+
+ public VariableUsedVisitor(PsiVariable variable) {
+ super();
+ this.variable = variable;
+ }
+
+ 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 referent = ref.resolve();
+ if (referent == null) {
+ return;
+ }
+ if (referent.equals(variable)) {
+ used = true;
+ }
+ }
+
+ public boolean isUsed() {
+ return used;
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java
new file mode 100644
index 000000000000..769666126ea8
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java
@@ -0,0 +1,232 @@
+package com.siyeh.ig.resources;
+
+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.ExpressionInspection;
+import com.siyeh.ig.GroupNames;
+import com.siyeh.ig.psiutils.TypeUtils;
+
+public class IOResourceInspection extends ExpressionInspection {
+
+ public String getDisplayName() {
+ return "I/O resource opened but not safely closed";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.RESOURCE_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiExpression expression = (PsiExpression) location;
+ final PsiType type = expression.getType();
+ final String text = type.getPresentableText();
+ return text + " should be opened in a try block, and closed in a finally block #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new IOResourceVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class IOResourceVisitor extends BaseInspectionVisitor {
+ private IOResourceVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitNewExpression(PsiNewExpression expression) {
+ super.visitNewExpression(expression);
+ if (!isIOResource(expression)) {
+ return;
+ }
+ final PsiElement parent = expression.getParent();
+ if(parent instanceof PsiExpressionList)
+ {
+ final PsiElement grandParent = parent.getParent();
+ if(grandParent instanceof PsiNewExpression &&
+ isIOResource((PsiNewExpression) grandParent))
+ {
+ return;
+ }
+ }
+ if (!(parent instanceof PsiAssignmentExpression)) {
+ registerError(expression);
+ return;
+ }
+ final PsiAssignmentExpression assignment = (PsiAssignmentExpression) parent;
+ final PsiExpression lhs = assignment.getLExpression();
+ if(!(lhs instanceof PsiReferenceExpression))
+ {
+ return;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) lhs).resolve();
+ if(referent == null || !(referent instanceof PsiVariable))
+ {
+ return;
+ }
+ final PsiVariable boundVariable = (PsiVariable) referent;
+ final PsiElement containingBlock = PsiTreeUtil.getParentOfType(expression, PsiCodeBlock.class);
+
+ if(isArgToResourceCreation(boundVariable, containingBlock))
+ {
+ return;
+ }
+ PsiElement currentContext = expression;
+ while (true) {
+ final PsiTryStatement tryStatement =
+ (PsiTryStatement) PsiTreeUtil.getParentOfType(currentContext, PsiTryStatement.class);
+ if (tryStatement == null) {
+ registerError(expression);
+ return;
+ }
+ if (resourceIsOpenedInTryAndClosedInFinally(tryStatement, expression, boundVariable)) {
+ return;
+ }
+ currentContext = tryStatement;
+ }
+
+ }
+
+ private boolean isArgToResourceCreation(PsiVariable boundVariable, PsiElement scope) {
+ final UsedAsIOResourceArgVisitor visitor = new UsedAsIOResourceArgVisitor(boundVariable);
+ scope.accept(visitor);
+ return visitor.usedAsArgToResourceCreation();
+ }
+
+ private static boolean resourceIsOpenedInTryAndClosedInFinally(PsiTryStatement tryStatement,
+ PsiExpression lhs, PsiVariable boundVariable) {
+ final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
+ if (finallyBlock == null) {
+ return false;
+ }
+ final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
+ if (tryBlock == null) {
+ return false;
+ }
+ if (!PsiTreeUtil.isAncestor(tryBlock, lhs, true)) {
+ return false;
+ }
+ return containsResourceClose(finallyBlock, boundVariable);
+ }
+
+ private static boolean containsResourceClose(PsiCodeBlock finallyBlock, PsiVariable boundVariable) {
+ final StreamCloseVisitor visitor = new StreamCloseVisitor(boundVariable);
+ finallyBlock.accept(visitor);
+ return visitor.containsStreamClose();
+ }
+
+ }
+
+ private static class StreamCloseVisitor extends PsiRecursiveElementVisitor {
+ private boolean containsStreamClose = false;
+ private PsiVariable streamToClose;
+
+ private StreamCloseVisitor(PsiVariable streamToClose) {
+ super();
+ this.streamToClose = streamToClose;
+ }
+
+ 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 call) {
+ super.visitMethodCallExpression(call);
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
+ if (methodExpression == null) {
+ return;
+ }
+ final String methodName = methodExpression.getReferenceName();
+ if (!"close".equals(methodName)) {
+ return;
+ }
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
+ if (qualifier == null) {
+ return;
+ }
+ if(!(qualifier instanceof PsiReferenceExpression))
+ {
+ return;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) qualifier).resolve();
+ if (referent.equals(streamToClose)) {
+ containsStreamClose = true;
+ }
+ }
+
+ public boolean containsStreamClose() {
+ return containsStreamClose;
+ }
+ }
+
+ private static class UsedAsIOResourceArgVisitor extends PsiRecursiveElementVisitor {
+ private boolean usedAsArgToResourceCreation = false;
+ private PsiVariable ioResource;
+
+ private UsedAsIOResourceArgVisitor(PsiVariable streamToClose) {
+ super();
+ this.ioResource = streamToClose;
+ }
+
+ 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 visitNewExpression(PsiNewExpression expression) {
+ super.visitNewExpression(expression);
+ if(!isIOResource(expression))
+ {
+ return;
+ }
+ final PsiExpressionList argList = expression.getArgumentList();
+ if(argList == null)
+ {
+ return;
+ }
+ final PsiExpression[] expressions = argList.getExpressions();
+ if(expressions == null || expressions.length == 0)
+ {
+ return;
+ }
+ final PsiExpression arg = expressions[0];
+ if(arg == null || !(arg instanceof PsiReferenceExpression))
+ {
+ return;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) arg).resolve();
+ if(referent ==null || !referent.equals(ioResource))
+ {
+ return;
+ }
+ usedAsArgToResourceCreation = true;
+ }
+
+ public boolean usedAsArgToResourceCreation() {
+ return usedAsArgToResourceCreation;
+ }
+ }
+
+ private static boolean isIOResource(PsiNewExpression expression) {
+ return TypeUtils.expressionHasTypeOrSubtype("java.io.InputStream", expression) ||
+ TypeUtils.expressionHasTypeOrSubtype("java.io.Writer", expression) ||
+ TypeUtils.expressionHasTypeOrSubtype("java.io.Reader", expression) ||
+ TypeUtils.expressionHasTypeOrSubtype("java.io.RandomAccessFile", expression) ||
+ TypeUtils.expressionHasTypeOrSubtype("java.io.OutputStream", expression);
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java
new file mode 100644
index 000000000000..c2eced37f273
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java
@@ -0,0 +1,186 @@
+package com.siyeh.ig.resources;
+
+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.ExpressionInspection;
+import com.siyeh.ig.GroupNames;
+
+public class JDBCResourceInspection extends ExpressionInspection {
+ private static String[] creationMethodClassName =
+ new String[]{
+ "java.sql.Driver",
+ "java.sql.DriverManager",
+ "java.sql.Connection",
+ "java.sql.Connection",
+ "java.sql.Connection",
+ "java.sql.Statement",
+ "java.sql.Statement",
+ };
+ private static String[] creationMethodName =
+ new String[]{
+ "connect",
+ "getConnection",
+ "createStatement",
+ "prepareStatement",
+ "prepareCall",
+ "executeQuery",
+ "getResultSet",
+ };
+
+ public String getDisplayName() {
+ return "JDBC resource opened but not safely closed";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.RESOURCE_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ final PsiExpression expression = (PsiExpression) location;
+ final PsiType type = expression.getType();
+ final String text = type.getPresentableText();
+ return "JDBC " + text + " should be opened in a try block, and closed in a finally block #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new JDBCResourceVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class JDBCResourceVisitor extends BaseInspectionVisitor {
+ private JDBCResourceVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ if (!isJDBCResourceCreation(expression)) {
+ return;
+ }
+ final PsiElement parent = expression.getParent();
+ if (!(parent instanceof PsiAssignmentExpression)) {
+ registerError(expression);
+ return;
+ }
+ final PsiAssignmentExpression assignment = (PsiAssignmentExpression) parent;
+ final PsiExpression lhs = assignment.getLExpression();
+ if (!(lhs instanceof PsiReferenceExpression)) {
+ return;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) lhs).resolve();
+ if (referent == null || !(referent instanceof PsiVariable)) {
+ return;
+ }
+ final PsiVariable boundVariable = (PsiVariable) referent;
+
+ PsiElement currentContext = expression;
+ while (true) {
+ final PsiTryStatement tryStatement =
+ (PsiTryStatement) PsiTreeUtil.getParentOfType(currentContext, PsiTryStatement.class);
+ if (tryStatement == null) {
+ registerError(expression);
+ return;
+ }
+ if (resourceIsOpenedInTryAndClosedInFinally(tryStatement, expression, boundVariable)) {
+ return;
+ }
+ currentContext = tryStatement;
+ }
+ }
+
+
+ private static boolean resourceIsOpenedInTryAndClosedInFinally(PsiTryStatement tryStatement,
+ PsiExpression lhs, PsiVariable boundVariable) {
+ final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
+ if (finallyBlock == null) {
+ return false;
+ }
+ final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
+ if (tryBlock == null) {
+ return false;
+ }
+ if (!PsiTreeUtil.isAncestor(tryBlock, lhs, true)) {
+ return false;
+ }
+ return containsResourceClose(finallyBlock, boundVariable);
+ }
+
+ private static boolean containsResourceClose(PsiCodeBlock finallyBlock, PsiVariable boundVariable) {
+ final ResourceCloseVisitor visitor = new ResourceCloseVisitor(boundVariable);
+ finallyBlock.accept(visitor);
+ return visitor.containsResourceClose();
+ }
+
+ }
+
+ private static class ResourceCloseVisitor extends PsiRecursiveElementVisitor {
+ private boolean containsResourceClose = false;
+ private PsiVariable streamToClose;
+
+ private ResourceCloseVisitor(PsiVariable streamToClose) {
+ super();
+ this.streamToClose = streamToClose;
+ }
+
+ 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 call) {
+ super.visitMethodCallExpression(call);
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
+ if (methodExpression == null) {
+ return;
+ }
+ final String methodName = methodExpression.getReferenceName();
+ if (!"close".equals(methodName)) {
+ return;
+ }
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
+ if (qualifier == null) {
+ return;
+ }
+ if (!(qualifier instanceof PsiReferenceExpression)) {
+ return;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) qualifier).resolve();
+ if (referent.equals(streamToClose)) {
+ containsResourceClose = true;
+ }
+ }
+
+ public boolean containsResourceClose() {
+ return containsResourceClose;
+ }
+ }
+
+ private static boolean isJDBCResourceCreation(PsiMethodCallExpression expression) {
+ final PsiMethod method = expression.resolveMethod();
+ if (method == null) {
+ return false;
+ }
+ final PsiClass containingClass = method.getContainingClass();
+ final String name = method.getName();
+ if (containingClass == null) {
+ return false;
+ }
+ final String className = containingClass.getQualifiedName();
+ for (int i = 0; i < creationMethodName.length; i++) {
+ if (name.equals(creationMethodName[i]) &&
+ className.equals(creationMethodClassName[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/SerialPersistentFieldsWithWrongSignatureInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/SerialPersistentFieldsWithWrongSignatureInspection.java
new file mode 100644
index 000000000000..4a759a087def
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/serialization/SerialPersistentFieldsWithWrongSignatureInspection.java
@@ -0,0 +1,71 @@
+package com.siyeh.ig.serialization;
+
+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.SerializationUtils;
+
+public class SerialPersistentFieldsWithWrongSignatureInspection extends ClassInspection {
+
+ public String getDisplayName() {
+ return "'serialPersistentFields' field not declared 'private static final ObjectStreamField[]'";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.SERIALIZATION_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "#ref field of a Serializable class is not declared 'private static final ObjectStreamField[]' #loc ";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new SerializableDefinesSerialVersionUIDVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class SerializableDefinesSerialVersionUIDVisitor extends BaseInspectionVisitor {
+ private SerializableDefinesSerialVersionUIDVisitor(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.isAnnotationType()) {
+ return;
+ }
+ if (!SerializationUtils.isSerializable(aClass)) {
+ return;
+ }
+ final PsiField[] fields = aClass.getFields();
+ for (int i = 0; i < fields.length; i++) {
+ final PsiField field = fields[i];
+ if (isSerialPersistentFields(field)) {
+ if (!field.hasModifierProperty(PsiModifier.PRIVATE) ||
+ !field.hasModifierProperty(PsiModifier.STATIC) ||
+ !field.hasModifierProperty(PsiModifier.FINAL)) {
+ registerFieldError(field);
+ } else {
+ final PsiType type = field.getType();
+ if (type != null) {
+ final String text = type.getCanonicalText();
+ if (!text.equals("java.io.ObjectStreamField[]")) {
+ registerFieldError(field);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean isSerialPersistentFields(PsiField field) {
+ final String fieldName = field.getName();
+ return "serialPersistentFields".equals(fieldName);
+ }
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/threading/CallToNativeMethodWhileLockedInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/CallToNativeMethodWhileLockedInspection.java
new file mode 100644
index 000000000000..4817dfeb168e
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/CallToNativeMethodWhileLockedInspection.java
@@ -0,0 +1,82 @@
+package com.siyeh.ig.threading;
+
+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 CallToNativeMethodWhileLockedInspection extends StatementInspection {
+
+ public String getDisplayName() {
+ return "Call to a native method while locked";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.THREADING_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Call to native method #ref() in a synchronized context #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new WaitNotInSynchronizedContextVisitor(this, inspectionManager, onTheFly);
+ }
+
+ private static class WaitNotInSynchronizedContextVisitor extends BaseInspectionVisitor {
+ private boolean m_inSynchronizedContext = false;
+
+ private WaitNotInSynchronizedContextVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ if (!m_inSynchronizedContext) {
+ return;
+ }
+ final PsiMethod method = expression.resolveMethod();
+ if(method == null)
+ {
+ return;
+ }
+ if (!method.hasModifierProperty(PsiModifier.NATIVE)) {
+ return;
+ }
+ final PsiClass containingClass = method.getContainingClass();
+ if(containingClass == null)
+ {
+ return;
+ }
+ final String className = containingClass.getQualifiedName();
+ if("java.lang.Object".equals(className))
+ {
+ return;
+ }
+ registerMethodCallError(expression);
+ }
+
+ public void visitMethod(PsiMethod method) {
+ final boolean wasInSynchronizedContext = m_inSynchronizedContext;
+ if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
+
+ m_inSynchronizedContext = true;
+ }
+ super.visitMethod(method);
+ if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
+
+ m_inSynchronizedContext = wasInSynchronizedContext;
+ }
+ }
+
+ public void visitSynchronizedStatement(PsiSynchronizedStatement psiSynchronizedStatement) {
+ final boolean wasInSynchronizedContext = m_inSynchronizedContext;
+ m_inSynchronizedContext = true;
+ super.visitSynchronizedStatement(psiSynchronizedStatement);
+ m_inSynchronizedContext = wasInSynchronizedContext;
+ }
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryConstructorInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryConstructorInspection.java
new file mode 100644
index 000000000000..e9bd5b51c5e6
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryConstructorInspection.java
@@ -0,0 +1,90 @@
+package com.siyeh.ig.verbose;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.siyeh.ig.*;
+
+public class UnnecessaryConstructorInspection extends ClassInspection {
+ private final UnnecessaryConstructorFix fix = new UnnecessaryConstructorFix();
+
+ public String getDisplayName() {
+ return "Redundant no-arg constructor";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.VERBOSE_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "No-arg constructor #ref is unnecessary #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new UnnecessaryConstructorVisitor(this, inspectionManager, onTheFly);
+ }
+
+ public InspectionGadgetsFix buildFix(PsiElement location) {
+ return fix;
+ }
+
+ private static class UnnecessaryConstructorFix extends InspectionGadgetsFix {
+ public String getName() {
+ return "Remove redundant constructor";
+ }
+
+ public void applyFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement nameIdentifier = descriptor.getPsiElement();
+ final PsiElement constructor = nameIdentifier.getParent();
+ deleteElement(constructor);
+ }
+
+ }
+
+ private static class UnnecessaryConstructorVisitor extends BaseInspectionVisitor {
+ private UnnecessaryConstructorVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitClass(PsiClass aClass) {
+
+ final PsiMethod[] constructors = aClass.getConstructors();
+ if (constructors == null) {
+ return;
+ }
+ if (constructors.length != 1) {
+ return;
+ }
+ final PsiMethod constructor = constructors[0];
+ if (!constructor.hasModifierProperty(PsiModifier.PUBLIC)) {
+ return;
+ }
+ final PsiParameterList parameterList = constructor.getParameterList();
+ if (parameterList == null) {
+ return;
+ }
+ if (parameterList.getParameters().length != 0) {
+ return;
+ }
+ final PsiCodeBlock body = constructor.getBody();
+ if (body == null) {
+ return;
+ }
+ final PsiStatement[] statements = body.getStatements();
+ if (statements == null) {
+ return;
+ }
+ if (statements.length == 0) {
+ registerMethodError(constructor);
+ }else if(statements.length == 1)
+ {
+ final PsiStatement statement = statements[0];
+ if("super();".equals(statement.getText()))
+ {
+ registerMethodError(constructor);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryLocalVariableInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryLocalVariableInspection.java
new file mode 100644
index 000000000000..44e749d0ae26
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryLocalVariableInspection.java
@@ -0,0 +1,267 @@
+package com.siyeh.ig.verbose;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.*;
+import com.siyeh.ig.psiutils.*;
+import com.siyeh.ig.fixes.InlineVariableFix;
+
+public class UnnecessaryLocalVariableInspection extends StatementInspection {
+
+ public String getDisplayName() {
+ return "Redundant local variable";
+ }
+
+ public String getGroupDisplayName() {
+ return GroupNames.VERBOSE_GROUP_NAME;
+ }
+
+ public String buildErrorString(PsiElement location) {
+ return "Local variable #ref is redundant #loc";
+ }
+
+ public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) {
+ return new UnnecessaryLocalVariableVisitor(this, inspectionManager, onTheFly);
+ }
+
+ public InspectionGadgetsFix buildFix(PsiElement location) {
+ return new InlineVariableFix();
+ }
+
+ private static class UnnecessaryLocalVariableVisitor extends BaseInspectionVisitor {
+ private UnnecessaryLocalVariableVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) {
+ super(inspection, inspectionManager, isOnTheFly);
+ }
+
+ public void visitLocalVariable(PsiLocalVariable variable) {
+ super.visitLocalVariable(variable);
+ if (isCopyVariable(variable)) {
+ registerVariableError(variable);
+ } else if (isImmediatelyReturned(variable)) {
+ registerVariableError(variable);
+ } else if (isImmediatelyAssigned(variable)) {
+ registerVariableError(variable);
+ }else if (isImmediatelyAssignedAsDeclaration(variable)) {
+ registerVariableError(variable);
+ }
+ }
+ }
+
+ private static boolean isCopyVariable(PsiVariable variable) {
+ final PsiExpression initializer = variable.getInitializer();
+ if (initializer == null) {
+ return false;
+ }
+ if (!(initializer instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ final PsiElement referent = ((PsiReference) initializer).resolve();
+ if (referent == null) {
+ return false;
+ }
+ if (!(referent instanceof PsiLocalVariable || referent instanceof PsiParameter)) {
+ return false;
+ }
+ final PsiCodeBlock containingScope =
+ (PsiCodeBlock) PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+ if (containingScope == null) {
+ return false;
+ }
+ final VariableAssignedVisitor visitor = new VariableAssignedVisitor(variable);
+ containingScope.accept(visitor);
+ if (visitor.isAssigned()) {
+ return false;
+ }
+
+ final PsiVariable initialization = (PsiVariable) referent;
+ final VariableAssignedVisitor visitor2 = new VariableAssignedVisitor(variable);
+ containingScope.accept(visitor2);
+ if (visitor2.isAssigned()) {
+ return false;
+ }
+ if (!initialization.hasModifierProperty(PsiModifier.FINAL)
+ && variable.hasModifierProperty(PsiModifier.FINAL)) {
+ if (variableIsUsedInInnerClass(containingScope, variable)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isImmediatelyReturned(PsiVariable variable) {
+
+ final PsiCodeBlock containingScope =
+ (PsiCodeBlock) PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+ if (containingScope == null) {
+ return false;
+ }
+ final PsiDeclarationStatement declarationStatement =
+ (PsiDeclarationStatement) PsiTreeUtil.getParentOfType(variable, PsiDeclarationStatement.class);
+ if (declarationStatement == null) {
+ return false;
+ }
+ PsiStatement nextStatement = null;
+ final PsiStatement[] statements = containingScope.getStatements();
+ for (int i = 0; i < statements.length - 1; i++) {
+ if (statements[i].equals(declarationStatement)) {
+ nextStatement = statements[i + 1];
+ }
+ }
+ if (nextStatement == null) {
+ return false;
+ }
+ if (!(nextStatement instanceof PsiReturnStatement)) {
+ return false;
+ }
+ final PsiReturnStatement returnStatement = (PsiReturnStatement) nextStatement;
+ final PsiExpression returnValue = returnStatement.getReturnValue();
+ if (returnValue == null) {
+ return false;
+ }
+ if (!(returnValue instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) returnValue).resolve();
+ if (referent == null || !referent.equals(variable)) {
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean isImmediatelyAssigned(PsiVariable variable) {
+
+ final PsiCodeBlock containingScope =
+ (PsiCodeBlock) PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+ if (containingScope == null) {
+ return false;
+ }
+ final PsiDeclarationStatement declarationStatement =
+ (PsiDeclarationStatement) PsiTreeUtil.getParentOfType(variable, PsiDeclarationStatement.class);
+ if (declarationStatement == null) {
+ return false;
+ }
+
+ PsiStatement nextStatement = null;
+ int followingStatementNumber = 0;
+ final PsiStatement[] statements = containingScope.getStatements();
+ for (int i = 0; i < statements.length - 1; i++) {
+ if (statements[i].equals(declarationStatement)) {
+ nextStatement = statements[i + 1];
+ followingStatementNumber = i + 2;
+ }
+ }
+ if (nextStatement == null) {
+ return false;
+ }
+ if (!(nextStatement instanceof PsiExpressionStatement)) {
+ return false;
+ }
+ final PsiExpressionStatement expressionStatement = (PsiExpressionStatement) nextStatement;
+ final PsiExpression expression = expressionStatement.getExpression();
+ if (expression == null) {
+ return false;
+ }
+ if (!(expression instanceof PsiAssignmentExpression)) {
+ return false;
+ }
+ final PsiExpression rhs = ((PsiAssignmentExpression) expression).getRExpression();
+ if (rhs == null) {
+ return false;
+ }
+ if (!(rhs instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) rhs).resolve();
+ if (referent == null || !referent.equals(variable)) {
+ return false;
+ }
+ for (int i = followingStatementNumber; i < statements.length; i++) {
+ if (variableIsUsedInStatement(statements[i], variable)) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+
+ private static boolean isImmediatelyAssignedAsDeclaration(PsiVariable variable) {
+
+ final PsiCodeBlock containingScope =
+ (PsiCodeBlock) PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+ if (containingScope == null) {
+ return false;
+ }
+ final PsiDeclarationStatement declarationStatement =
+ (PsiDeclarationStatement) PsiTreeUtil.getParentOfType(variable, PsiDeclarationStatement.class);
+ if (declarationStatement == null) {
+ return false;
+ }
+
+ PsiStatement nextStatement = null;
+ int followingStatementNumber = 0;
+ final PsiStatement[] statements = containingScope.getStatements();
+ for (int i = 0; i < statements.length - 1; i++) {
+ if (statements[i].equals(declarationStatement)) {
+ nextStatement = statements[i + 1];
+ followingStatementNumber = i + 2;
+ }
+ }
+ if (nextStatement == null) {
+ return false;
+ }
+ if (!(nextStatement instanceof PsiDeclarationStatement)) {
+ return false;
+ }
+ final PsiDeclarationStatement declaration = (PsiDeclarationStatement) nextStatement;
+ final PsiElement[] declarations = declaration.getDeclaredElements();
+ if (declarations == null) {
+ return false;
+ }
+ if (declarations.length != 1) {
+ return false;
+ }
+ if (!(declarations[0] instanceof PsiVariable)) {
+ return false;
+ }
+
+ final PsiExpression rhs = ((PsiVariable) declarations[0]).getInitializer();
+ if (rhs == null) {
+ return false;
+ }
+ if (!(rhs instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ final PsiElement referent = ((PsiReferenceExpression) rhs).resolve();
+ if (referent == null || !referent.equals(variable)) {
+ return false;
+ }
+ for (int i = followingStatementNumber; i < statements.length; i++) {
+ if (variableIsUsedInStatement(statements[i], variable)) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ private static boolean variableIsUsedInInnerClass(PsiCodeBlock block,
+ PsiVariable variable) {
+
+ final VariableUsedInInnerClassVisitor visitor
+ = new VariableUsedInInnerClassVisitor(variable);
+ block.accept(visitor);
+ return visitor.isUsedInInnerClass();
+ }
+
+ private static boolean variableIsUsedInStatement(PsiStatement statement,
+ PsiVariable variable) {
+
+ final VariableUsedVisitor visitor
+ = new VariableUsedVisitor(variable);
+ statement.accept(visitor);
+ return visitor.isUsed();
+ }
+
+}
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionCaught.html b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionCaught.html
new file mode 100644
index 000000000000..2cae3deb7ca6
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionCaught.html
@@ -0,0 +1,12 @@
+
+ |
+
+This inspection reports any instances of catch clauses
+which catch inappropriate exceptions. Some exceptions, for instance
+java.lang.NullPointerException and
+java.lang.IllegalMonitorStateException represent programming errors
+and so should almost certainly not be caught in production code.
+
+Use the list below to specify which exceptions should be flagged by this inspection.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html
new file mode 100644
index 000000000000..03cd3e41ca26
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html
@@ -0,0 +1,11 @@
+
+ |
+
+This inspection reports any instances of throws clauses on
+methods which throw inappropriate exceptions. One use of this inspection would be to warn of
+throws clauses which throw overly generic exceptions
+(e.g. java.lang.Exception) or
+
+Use the list below to specify which exceptions should be flagged by this inspection.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionThrown.html b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionThrown.html
new file mode 100644
index 000000000000..7925dd4867b8
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionThrown.html
@@ -0,0 +1,12 @@
+
+ |
+
+This inspection reports any instances of throw statements
+which throw inappropriate exceptions. One use of this inspection would be to warn of
+throw statements which throw overly generic exceptions
+(e.g. java.lang.Exception or
+java.io.IOException).
+
+Use the list below to specify which exceptions should be flagged by this inspection.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/CallToNativeMethodWhileLocked.html b/plugins/InspectionGadgets/src/inspectionDescriptions/CallToNativeMethodWhileLocked.html
new file mode 100644
index 000000000000..de328b3f412b
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/CallToNativeMethodWhileLocked.html
@@ -0,0 +1,8 @@
+
+ |
+
+This inspection reports any to methods declared native while in
+a synchronized block or method. While not necessarily representing a problem, such calls cause
+an expensive context switch, and are best kept out of synchronized contexts, if possible.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html
new file mode 100644
index 000000000000..89aee1d1895b
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html
@@ -0,0 +1,15 @@
+
+
+ |
+
+This inspection reports any I/O resource which is not opened in a try
+block and closed in the corresponding finally block. Such resources may
+be inadvertantly leaked if an exception is thrown before the resouce is closed. I/O resources reported
+by this inspection include any instances of java.io.InputStream,
+ java.io.OutputStream,
+ java.io.Reader,
+ java.io.Writer and
+ java.io.RandomAccessFile . I/O resources which are wrapped by other I/O resources
+are not reported, as the wrapped resource will be closed by the wrapping resource.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceofChain.html b/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceofChain.html
new file mode 100644
index 000000000000..ef7c159a25cb
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceofChain.html
@@ -0,0 +1,9 @@
+
+ |
+
+This inspection reports any chains of if-else statements all of whose conditions are instanceof expressions
+(or combinations of such expressions). Such constructions usually indicate a failure of object-oriented design, which
+dictates that such type-based dispatch should be done via polymorphic method calls rather than explicit chains
+of type tests.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html
new file mode 100644
index 000000000000..a2c40828145d
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html
@@ -0,0 +1,13 @@
+
+ |
+
+This inspection reports any JDBC resource which is not opened in a try
+block and closed in the corresponding finally block. Such resources may
+be inadvertantly leaked if an exception is thrown before the resouce is closed. JDBC resources reported
+by this inspection include any instances of java.sql.Connection,
+ java.sql.Statement,
+ java.sql.PreparedStatement,
+ java.sql.CallableStatement,
+and java.sql.ResultSet.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MisorderedAssertEqualsParameters.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MisorderedAssertEqualsParameters.html
new file mode 100644
index 000000000000..607fc83778e6
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MisorderedAssertEqualsParameters.html
@@ -0,0 +1,8 @@
+
+ |
+This inspection reports any calls to JUnit assertEquals() which have
+a non-literal as the expected result argument and a literal as the actual result argument. Such calls
+will behave fine for assertions which pass, but may give confusing error reports if their expected and actual
+arguments differ.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNameDiffersFromOverriddenParameter.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNameDiffersFromOverriddenParameter.html
new file mode 100644
index 000000000000..a0be21b5502f
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNameDiffersFromOverriddenParameter.html
@@ -0,0 +1,8 @@
+
+ |
+
+This inspection reports any instances of parameters which have different names from corresponding
+parameters in methods they override. While legal in Java, such inconsistent names may be confusing,
+and lessen the documentation benefits of good naming practices.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SerialPersistentFieldsWithWrongSignature.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SerialPersistentFieldsWithWrongSignature.html
new file mode 100644
index 000000000000..bceb5aab0fb1
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SerialPersistentFieldsWithWrongSignature.html
@@ -0,0 +1,7 @@
+
+ |
+
+This inspection reports any instances of Serializable classes whose serialPersistentFields field.
+is not declared private static final ObjectStreamField.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SimpleDateFormatWithoutLocale.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SimpleDateFormatWithoutLocale.html
new file mode 100644
index 000000000000..415499825e25
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SimpleDateFormatWithoutLocale.html
@@ -0,0 +1,8 @@
+
+ |
+
+This inspection reports any instantiations of java.util.SimpleDateFormat
+which do not specify a java.util.Locale.
+Such calls are usually incorrect in an internationalized environment.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableJUnitAssertion.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableJUnitAssertion.html
new file mode 100644
index 000000000000..07749c1844dc
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableJUnitAssertion.html
@@ -0,0 +1,7 @@
+
+ |
+This inspection reports any JUnit assertTrue calls
+which can be replaced by equivalent assertEquals calls. assertEquals
+calls will normally give better error messages in case of test failure than assertTrue can.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticCallOnSubclass.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticCallOnSubclass.html
new file mode 100644
index 000000000000..bbd1488d3da2
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticCallOnSubclass.html
@@ -0,0 +1,9 @@
+
+ |
+
+This inspection reports any instances of static method calls where the call is qualified
+by a subclass of the declaring class, rather than the declaring class itself
+(e.g. MyThreadSubclass.sleep()). Java allows such qualification, but such calls
+may be confusing, and may indicate a subtle confusion of inheritance and overriding.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringBufferField.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringBufferField.html
new file mode 100644
index 000000000000..9f7cabddb87b
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringBufferField.html
@@ -0,0 +1,9 @@
+
+ |
+
+This inspection reports any instances of fields with type
+java.lang.StringBuffer or java.lang.StringBuilder.
+StringBuffer fields can grow without limit, and are often the cause of
+memory leaks.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TestCaseInProductCode.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TestCaseInProductCode.html
new file mode 100644
index 000000000000..52c38e6729e2
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TestCaseInProductCode.html
@@ -0,0 +1,8 @@
+
+ |
+
+This inspection reports any instances of JUnit test cases in product source trees.
+This most likely indicates programmer error, and can result in test code being shipped
+into production.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnconstructableTestCase.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnconstructableTestCase.html
new file mode 100644
index 000000000000..4ec9c2ea7ac2
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnconstructableTestCase.html
@@ -0,0 +1,9 @@
+
+ |
+
+This inspection reports any instances of non-abstract JUnit test cases which do not
+expose a public no-arg constructor or a public constructor which takes a single string
+as an argument. Such test cases will be unrunnable by most JUnit test runners, including
+IDEA's.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryConstructor.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryConstructor.html
new file mode 100644
index 000000000000..0ff685749819
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryConstructor.html
@@ -0,0 +1,8 @@
+
+ |
+
+This inspection reports any instances of unnecessary public no-arg constructors.
+If such a constructor is the only constructor for a class and performs no initialization,
+it can be safely removed.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryLocalVariable.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryLocalVariable.html
new file mode 100644
index 000000000000..066d7ee5312f
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryLocalVariable.html
@@ -0,0 +1,10 @@
+
+ |
+
+This inspection reports any instances of unnecessary local variables, which add
+nothing to the comprehensibility of a method. Variables caught include local variables
+which are immediately returned, local variables that are immediately assigned to another
+variable and then not used, and local variables which always have the same value as another
+local variable or parameter.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UseOfAnotherObjectsPrivateField.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UseOfAnotherObjectsPrivateField.html
new file mode 100644
index 000000000000..0218c5610bd0
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UseOfAnotherObjectsPrivateField.html
@@ -0,0 +1,11 @@
+
+ |
+
+This inspection reports any uses of another object's private or protected fields. Java
+allows the use of such fields for objects of the same class as the current objects, but
+some coding styles discourage this use. Additionally, such direct access to private fields
+may fail in component-oriented architectures such (e.g. Spring, Hibernate) which expect all access
+to other objects to be through method calls so as to allow the framework to mediate all access
+using proxies.
+ |
| Powered by InspectionGadgets |
+
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/FeatureEnvy.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/FeatureEnvy.java
new file mode 100644
index 000000000000..65ead907f664
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/FeatureEnvy.java
@@ -0,0 +1,31 @@
+package com.siyeh.igtest.abstraction;
+
+class TestFeatureEnvySuper {
+ void foo1() {
+ }
+
+ void foo2() {
+ }
+
+ void foo3() {
+ }
+}
+
+class TestFeatureEnvySuper2 {
+ void test() {
+ TestFeatureEnvySuper test = new TestFeatureEnvySuper();
+ test.foo1();
+ test.foo2();
+ test.foo3();
+ }
+}
+
+public class FeatureEnvy extends TestFeatureEnvySuper {
+ class Inner {
+ void test() {
+ foo1();
+ foo2();
+ foo3();
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java
new file mode 100644
index 000000000000..edee3629f52f
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java
@@ -0,0 +1,14 @@
+package com.siyeh.igtest.bugs;
+
+public class StaticCallOnSubclass {
+
+ public void foo() throws InterruptedException {
+ Thread.sleep(1000L);
+ InnerThread.sleep(1000L);
+ }
+
+ class InnerThread extends Thread
+ {
+
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/encapsulation/UseOfAnotherObjectsPrivateFieldInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/encapsulation/UseOfAnotherObjectsPrivateFieldInspection.java
new file mode 100644
index 000000000000..fa2ef949c267
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/encapsulation/UseOfAnotherObjectsPrivateFieldInspection.java
@@ -0,0 +1,16 @@
+package com.siyeh.igtest.encapsulation;
+
+public class UseOfAnotherObjectsPrivateFieldInspection {
+ public int foo;
+ protected int bar;
+ private int baz;
+
+ public void fooBar(UseOfAnotherObjectsPrivateFieldInspection copy)
+ {
+ foo = copy.foo;
+ bar = copy.bar;
+ baz = copy.baz;
+ foo = this.baz;
+ foo = baz;
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase1.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase1.java
new file mode 100644
index 000000000000..de82bb98e5d2
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase1.java
@@ -0,0 +1,12 @@
+package com.siyeh.igtest.junit;
+
+import junit.framework.TestCase;
+
+public class UnconstructableTestCase1 extends TestCase
+{
+ private UnconstructableTestCase1()
+ {
+ System.out.println("");
+ }
+
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase2.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase2.java
new file mode 100644
index 000000000000..182534298c33
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase2.java
@@ -0,0 +1,12 @@
+package com.siyeh.igtest.junit;
+
+import junit.framework.TestCase;
+
+public class UnconstructableTestCase2 extends TestCase
+{
+ public UnconstructableTestCase2(Object foo)
+ {
+ System.out.println("");
+ }
+
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase3.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase3.java
new file mode 100644
index 000000000000..dba593783e86
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase3.java
@@ -0,0 +1,12 @@
+package com.siyeh.igtest.junit;
+
+import junit.framework.TestCase;
+
+public class UnconstructableTestCase3 extends TestCase
+{
+ public UnconstructableTestCase3()
+ {
+ System.out.println("");
+ }
+
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase4.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase4.java
new file mode 100644
index 000000000000..78456782767d
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/UnconstructableTestCase4.java
@@ -0,0 +1,12 @@
+package com.siyeh.igtest.junit;
+
+import junit.framework.TestCase;
+
+public class UnconstructableTestCase4 extends TestCase
+{
+ public UnconstructableTestCase4(String foo)
+ {
+ System.out.println("");
+ }
+
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/package2/Test.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/package2/Test.java
new file mode 100644
index 000000000000..9fef1dd1e9c1
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/package2/Test.java
@@ -0,0 +1,4 @@
+package com.siyeh.igtest.naming.package2;
+
+public class Test {
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/package2/Test2.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/package2/Test2.java
new file mode 100644
index 000000000000..caf8fe6d5308
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/package2/Test2.java
@@ -0,0 +1,4 @@
+package com.siyeh.igtest.naming.package2;
+
+public class Test2 {
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/portability/AutoUnboxingInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/portability/AutoUnboxingInspection.java
new file mode 100644
index 000000000000..ea7634e30c7a
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/portability/AutoUnboxingInspection.java
@@ -0,0 +1,15 @@
+package com.siyeh.igtest.portability;
+
+public class AutoUnboxingInspection {
+ public void foo() {
+ Integer bar = 3;
+ int baz = new Integer(3);
+ if (new Integer(3) == 3) {
+ return;
+ }
+ if (new Integer(3) + 3 == 3) {
+ return;
+ }
+ Integer x = 3;
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/JDBCResourceInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/JDBCResourceInspection.java
new file mode 100644
index 000000000000..c00cf709e3d8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/resources/JDBCResourceInspection.java
@@ -0,0 +1,144 @@
+package com.siyeh.igtest.resources;
+
+import java.sql.*;
+
+public class JDBCResourceInspection {
+ private Driver driver;
+
+ public void foo() throws SQLException {
+ Connection connection = null;
+ try {
+ connection = driver.connect("foo", null);
+ } finally {
+ connection.close();
+ }
+
+ }
+
+ public void foo2() throws SQLException {
+ Connection connection = null;
+ try {
+ connection = driver.connect("foo", null);
+ } finally {
+ }
+ }
+
+
+ public void foo3() throws SQLException {
+ Connection connection = null;
+ try {
+ connection = driver.connect("foo", null);
+ connection.createStatement();
+ } finally {
+ connection.close();
+ }
+
+ }
+
+ public void foo4() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.createStatement();
+ } finally {
+ connection.close();
+ }
+
+ }
+
+ public void foo5() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.createStatement();
+ } finally {
+ statement.close();
+ connection.close();
+ }
+
+ }
+
+ public void foo6() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.prepareStatement("foo");
+ } finally {
+ connection.close();
+ }
+
+ }
+
+ public void foo7() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.prepareStatement("foo");
+ } finally {
+ statement.close();
+ connection.close();
+ }
+
+ }
+
+ public void foo8() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.prepareCall("foo");
+ } finally {
+ connection.close();
+ }
+
+ }
+
+ public void foo9() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.prepareCall("foo");
+ } finally {
+ statement.close();
+ connection.close();
+ }
+
+ }
+
+ public void foo10() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ ResultSet resultSet = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.prepareCall("foo");
+ resultSet = statement.executeQuery("foo");
+ } finally {
+ statement.close();
+ connection.close();
+ }
+
+ }
+
+ public void foo11() throws SQLException {
+ Connection connection = null;
+ Statement statement = null;
+ ResultSet resultSet = null;
+ try {
+ connection = driver.connect("foo", null);
+ statement = connection.prepareCall("foo");
+ resultSet = statement.executeQuery("foo");
+ } finally {
+ resultSet.close();
+ statement.close();
+ connection.close();
+ }
+
+ }
+
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryBlockStatementInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryBlockStatementInspection.java
new file mode 100644
index 000000000000..4d4d0a19a353
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryBlockStatementInspection.java
@@ -0,0 +1,9 @@
+package com.siyeh.igtest.verbose;
+
+public class UnnecessaryBlockStatementInspection {
+ public static void main(String[] args) {
+ {
+ System.out.println("3");
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryLocalVariableInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryLocalVariableInspection.java
new file mode 100644
index 000000000000..99a25eaa4a37
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryLocalVariableInspection.java
@@ -0,0 +1,22 @@
+package com.siyeh.igtest.verbose;
+
+public class UnnecessaryLocalVariableInspection {
+
+ public int foo() {
+ int a = 2;
+ int b = a;
+ return b;
+ }
+
+ public int bar() {
+ int b = 3;
+ return b;
+ }
+
+ public int baz() {
+ int a;
+ int b = 3;
+ a = b;
+ return a;
+ }
+}