unused declaration: find code reachable only from tests

This commit is contained in:
Anna Kozlova
2016-08-29 20:37:32 +03:00
parent 9ffa2a88b3
commit 96077ea349
4 changed files with 57 additions and 8 deletions
@@ -67,6 +67,7 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
public boolean ADD_APPLET_TO_ENTRIES = true;
public boolean ADD_SERVLET_TO_ENTRIES = true;
public boolean ADD_NONJAVA_TO_ENTRIES = true;
protected boolean TEST_ENTRY_POINTS = true;
public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name");
public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
@@ -128,6 +129,14 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
return ADD_NONJAVA_TO_ENTRIES;
}
public boolean isTestEntryPoints() {
return TEST_ENTRY_POINTS;
}
public void setTestEntryPoints(boolean testEntryPoints) {
TEST_ENTRY_POINTS = testEntryPoints;
}
@Override
@NotNull
public String getDisplayName() {
@@ -153,12 +162,19 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
for (EntryPoint extension : myExtensions) {
extension.readExternal(node);
}
final String testEntriesAttr = node.getAttributeValue("test_entries");
TEST_ENTRY_POINTS = testEntriesAttr == null || Boolean.parseBoolean(testEntriesAttr);
}
@Override
public void writeSettings(@NotNull Element node) throws WriteExternalException {
myLocalInspectionBase.writeSettings(node);
writeUnusedDeclarationSettings(node);
if (!TEST_ENTRY_POINTS) {
node.setAttribute("test_entries", Boolean.toString(false));
}
}
protected void writeUnusedDeclarationSettings(Element node) throws WriteExternalException {
@@ -23,13 +23,16 @@ import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
import com.intellij.codeInspection.ex.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.IncorrectOperationException;
import gnu.trove.THashMap;
import org.jdom.Element;
@@ -109,7 +112,17 @@ public class RefJavaManagerImpl extends RefJavaManager {
public boolean isEntryPoint(final RefElement element) {
UnusedDeclarationInspectionBase tool = getDeadCodeTool(element);
return tool != null && tool.isEntryPoint(element);
return tool != null && tool.isEntryPoint(element) && isTestSource(tool, element);
}
private static boolean isTestSource(UnusedDeclarationInspectionBase tool, RefElement refElement) {
if (tool.isTestEntryPoints()) return true;
final PsiElement element = refElement.getElement();
final VirtualFile file = PsiUtilCore.getVirtualFile(element);
if (file != null) {
return !ProjectRootManager.getInstance(element.getProject()).getFileIndex().isInTestSourceContent(file);
}
return false;
}
@Nullable
@@ -25,6 +25,9 @@ import com.intellij.codeInspection.reference.RefVisitor;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
@@ -123,10 +126,31 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
GridBagConstraints gc = new GridBagConstraints();
gc.weightx = 1;
gc.weighty = 0;
gc.insets = JBUI.insets(0, 20, 2, 0);
gc.fill = GridBagConstraints.HORIZONTAL;
gc.anchor = GridBagConstraints.NORTHWEST;
gc.gridx = 0;
gc.gridy = GridBagConstraints.RELATIVE;
add(new JBLabel("When entry point is located in test sources:"), gc);
final JBRadioButton asEntryPoint = new JBRadioButton("Treat as entry point", isTestEntryPoints());
final JBRadioButton asUnused = new JBRadioButton("Mark callees as unused", !isTestEntryPoints());
final ButtonGroup group = new ButtonGroup();
group.add(asEntryPoint);
group.add(asUnused);
final ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setTestEntryPoints(asEntryPoint.isSelected());
}
};
asEntryPoint.addActionListener(listener);
asUnused.addActionListener(listener);
add(asEntryPoint, gc);
add(asUnused, gc);
add(new TitledSeparator(), gc);
gc.insets = JBUI.insets(0, 20, 2, 0);
myMainsCheckbox = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option.main"));
myMainsCheckbox.setSelected(ADD_MAINS_TO_ENTRIES);
myMainsCheckbox.addActionListener(new ActionListener() {
@@ -136,7 +160,7 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
}
});
gc.gridy = 0;
add(myMainsCheckbox, gc);
myAppletToEntries = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option.applet"));
@@ -147,7 +171,6 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
ADD_APPLET_TO_ENTRIES = myAppletToEntries.isSelected();
}
});
gc.gridy++;
add(myAppletToEntries, gc);
myServletToEntries = new JCheckBox(InspectionsBundle.message("inspection.dead.code.option.servlet"));
@@ -158,7 +181,6 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
ADD_SERVLET_TO_ENTRIES = myServletToEntries.isSelected();
}
});
gc.gridy++;
add(myServletToEntries, gc);
for (final EntryPoint extension : myExtensions) {
@@ -171,7 +193,6 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
extension.setSelected(extCheckbox.isSelected());
}
});
gc.gridy++;
add(extCheckbox, gc);
}
}
@@ -186,11 +207,9 @@ public class UnusedDeclarationInspection extends UnusedDeclarationInspectionBase
}
});
gc.gridy++;
add(myNonJavaCheckbox, gc);
gc.fill = GridBagConstraints.NONE;
gc.gridy++;
gc.weighty = 1;
final JPanel btnPanel = new JPanel(new VerticalFlowLayout());
btnPanel.add(EntryPointsManagerImpl.createConfigureClassPatternsButton());
@@ -435,6 +435,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
RefJavaElement refElement = (RefJavaElement)refEntity;
if (!compareVisibilities(refElement, localInspectionTool)) return;
if (!(getContext().getUIOptions().FILTER_RESOLVED_ITEMS && getIgnoredRefElements().contains(refElement)) && refElement.isValid() && getFilter().accepts(refElement)) {
if (getTool().isEntryPoint(refElement)) return;
registerContentEntry(refEntity, RefJavaUtil.getInstance().getPackageName(refEntity));
}
}