unused inspection: treat fields as unused if they are implicitly write but not implicitly read (IDEA-118095)

This commit is contained in:
Anna Kozlova
2016-06-28 18:54:40 +03:00
parent 3fde2cffb2
commit f1ad5bc4a6
9 changed files with 95 additions and 14 deletions
@@ -18,7 +18,6 @@ package com.intellij.codeInspection.deadCode;
import com.intellij.ToolExtensionPoints;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase;
import com.intellij.codeInspection.*;
@@ -37,7 +36,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.VirtualFile;
@@ -372,7 +370,7 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
public boolean isEntryPoint(@NotNull RefElement owner) {
final PsiElement element = owner.getElement();
if (RefUtil.isImplicitUsage(element)) return true;
if (isImplicitUsage(element)) return true;
if (element instanceof PsiModifierListOwner) {
final EntryPointsManager entryPointsManager = EntryPointsManager.getInstance(element.getProject());
if (entryPointsManager.isEntryPoint(element)) {
@@ -389,6 +387,11 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
return false;
}
private static boolean isImplicitUsage(PsiElement element) {
return element instanceof PsiField ? RefUtil.isImplicitRead(element)
: RefUtil.isImplicitUsage(element);
}
public boolean isEntryPoint(@NotNull PsiElement element) {
final Project project = element.getProject();
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
@@ -417,11 +420,7 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
return true;
}
}
final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
for (ImplicitUsageProvider provider : implicitUsageProviders) {
if (provider.isImplicitUsage(element)) return true;
}
return false;
return isImplicitUsage(element);
}
public boolean isGlobalEnabledInEditor() {
@@ -21,7 +21,6 @@ import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -122,7 +121,7 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField {
refUtil.addReferences(psiField, this, psiField);
}
if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant) {
if (psiField.getInitializer() != null || psiField instanceof PsiEnumConstant || RefUtil.isWriteImplicitly(psiField)) {
if (!checkFlag(USED_FOR_WRITING_MASK)) {
setFlag(true, ASSIGNED_ONLY_IN_INITIALIZER_MASK);
setFlag(true, USED_FOR_WRITING_MASK);
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems/>
@@ -0,0 +1,11 @@
public class MyMTest {
@org.mockito.Mock
private String myFoo;
{
System.out.println(myFoo);
}
@org.junit.Test
public void testName() throws Exception {}
}
@@ -164,6 +164,10 @@ public class UnusedDeclarationTest extends InspectionTestCase {
doTest();
}
public void testMockedField() {
doTest();
}
public void testConstructorCalls() {
doTest();
}
@@ -41,6 +41,14 @@ public class RefUtil {
return false;
}
public static boolean isImplicitRead(PsiElement element) {
final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
for (ImplicitUsageProvider provider : implicitUsageProviders) {
if (provider.isImplicitRead(element)) return true;
}
return false;
}
public static boolean contains(RefEntity element, @NotNull Collection<RefEntity> entities){
for (RefEntity refEntity : entities) {
if (Comparing.equal(refEntity, element)) {
@@ -49,4 +57,12 @@ public class RefUtil {
}
return false;
}
public static boolean isWriteImplicitly(PsiElement element) {
final ImplicitUsageProvider[] implicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
for (ImplicitUsageProvider provider : implicitUsageProviders) {
if (provider.isImplicitWrite(element)) return true;
}
return false;
}
}
+1
View File
@@ -62,6 +62,7 @@
<codeInsight.externalLibraryResolver implementation="com.intellij.execution.junit.codeInsight.JUnitExternalLibraryResolver"/>
<junitListener implementation="com.intellij.junit4.JUnitTestDiscoveryListener"/>
<runConfigurationProducer implementation="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer"/>
<implicitUsageProvider implementation="com.intellij.execution.junit2.inspection.JUnitImplicitUsageProvider"/>
</extensions>
<extensionPoints>
@@ -104,10 +104,6 @@ public class JUnitEntryPoint extends EntryPoint {
@Override
public String[] getIgnoreAnnotations() {
return new String[]{"org.junit.Rule",
"org.mockito.Mock",
"org.mockito.Spy",
"org.mockito.Captor",
"org.mockito.InjectMocks",
"org.junit.ClassRule",
"org.junit.experimental.theories.DataPoint"};
}
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.junit2.inspection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiParameter;
import java.util.Arrays;
import java.util.List;
public class JUnitImplicitUsageProvider implements ImplicitUsageProvider {
private static final String MOCK = "org.mockito.Mock";
private static final List<String> INJECTED_FIELD_ANNOTATIONS = Arrays.asList(
MOCK,
"org.mockito.Spy",
"org.mockito.Captor",
"org.mockito.InjectMocks");
@Override
public boolean isImplicitUsage(PsiElement element) {
return isImplicitWrite(element);
}
@Override
public boolean isImplicitRead(PsiElement element) {
return false;
}
@Override
public boolean isImplicitWrite(PsiElement element) {
if (element instanceof PsiParameter) {
return AnnotationUtil.isAnnotated((PsiParameter)element, MOCK, false);
}
return element instanceof PsiField && AnnotationUtil.isAnnotated((PsiField) element, INJECTED_FIELD_ANNOTATIONS);
}
}