mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
coverage: separate options for implicit & empty constructors
This commit is contained in:
@@ -654,10 +654,7 @@ public class JavaCoverageEngine extends CoverageEngine {
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedCode(Project project, String qualifiedName, Object lineData) {
|
||||
if (JavaCoverageOptionsProvider.getInstance(project).ignoreEmptyPrivateConstructors()) {
|
||||
PsiClass psiClass = ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), qualifiedName));
|
||||
return PackageAnnotator.isGeneratedDefaultConstructor(psiClass, ((LineData)lineData).getMethodSignature());
|
||||
}
|
||||
if (JavaCoverageOptionsProvider.getInstance(project).isGeneratedConstructor(qualifiedName, ((LineData)lineData).getMethodSignature())) return true;
|
||||
return super.isGeneratedCode(project, qualifiedName, lineData);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package com.intellij.coverage;
|
||||
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class JavaCoverageOptions extends CoverageOptions {
|
||||
|
||||
@@ -57,12 +57,14 @@ public class JavaCoverageOptions extends CoverageOptions {
|
||||
|
||||
private static class JavaCoverageOptionsEditor {
|
||||
|
||||
private JPanel myPanel = new JPanel(new BorderLayout(0, 10));
|
||||
private JCheckBox myCheckBox = new JCheckBox("Ignore empty private and implicit constructors", true);
|
||||
private JPanel myPanel = new JPanel(new VerticalFlowLayout());
|
||||
private JCheckBox myImplicitCheckBox = new JCheckBox("Ignore implicit constructors", true);
|
||||
private JCheckBox myEmptyCheckBox = new JCheckBox("Ignore empty private constructors of utility classes", true);
|
||||
|
||||
public JavaCoverageOptionsEditor() {
|
||||
myPanel.setBorder(IdeBorderFactory.createTitledBorder("Java coverage"));
|
||||
myPanel.add(myCheckBox, BorderLayout.NORTH);
|
||||
myPanel.add(myImplicitCheckBox);
|
||||
myPanel.add(myEmptyCheckBox);
|
||||
}
|
||||
|
||||
public JPanel getComponent() {
|
||||
@@ -70,15 +72,18 @@ public class JavaCoverageOptions extends CoverageOptions {
|
||||
}
|
||||
|
||||
public boolean isModified(JavaCoverageOptionsProvider provider) {
|
||||
return myCheckBox.isSelected() != provider.ignoreEmptyPrivateConstructors();
|
||||
return myImplicitCheckBox.isSelected() != provider.ignoreImplicitConstructors() ||
|
||||
myEmptyCheckBox.isSelected() != provider.ignoreEmptyPrivateConstructors();
|
||||
}
|
||||
|
||||
public void apply(JavaCoverageOptionsProvider provider) {
|
||||
provider.setIgnoreEmptyPrivateConstructors(myCheckBox.isSelected());
|
||||
provider.setIgnoreImplicitConstructors(myImplicitCheckBox.isSelected());
|
||||
provider.setIgnoreEmptyPrivateConstructors(myEmptyCheckBox.isSelected());
|
||||
}
|
||||
|
||||
public void reset(JavaCoverageOptionsProvider provider) {
|
||||
myCheckBox.setSelected(provider.ignoreEmptyPrivateConstructors());
|
||||
myImplicitCheckBox.setSelected(provider.ignoreImplicitConstructors());
|
||||
myEmptyCheckBox.setSelected(provider.ignoreEmptyPrivateConstructors());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
package com.intellij.coverage;
|
||||
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@State(
|
||||
@@ -27,11 +31,23 @@ import org.jetbrains.annotations.Nullable;
|
||||
)
|
||||
public class JavaCoverageOptionsProvider implements PersistentStateComponent<JavaCoverageOptionsProvider.State> {
|
||||
private State myState = new State();
|
||||
|
||||
private Project myProject;
|
||||
|
||||
public JavaCoverageOptionsProvider(Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public boolean ignoreImplicitConstructors() {
|
||||
return myState.myIgnoreImplicitConstructors;
|
||||
}
|
||||
|
||||
public static JavaCoverageOptionsProvider getInstance(Project project) {
|
||||
return ServiceManager.getService(project, JavaCoverageOptionsProvider.class);
|
||||
}
|
||||
|
||||
public void setIgnoreImplicitConstructors(boolean state) {
|
||||
myState.myIgnoreImplicitConstructors = state;
|
||||
}
|
||||
|
||||
public void setIgnoreEmptyPrivateConstructors(boolean state) {
|
||||
myState.myIgnoreEmptyPrivateConstructors = state;
|
||||
@@ -41,6 +57,14 @@ public class JavaCoverageOptionsProvider implements PersistentStateComponent<Jav
|
||||
return myState.myIgnoreEmptyPrivateConstructors;
|
||||
}
|
||||
|
||||
public boolean isGeneratedConstructor(String qualifiedName, String methodSignature) {
|
||||
if (myState.myIgnoreImplicitConstructors || myState.myIgnoreEmptyPrivateConstructors) {
|
||||
PsiClass psiClass = ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(myProject), qualifiedName));
|
||||
return PackageAnnotator.isGeneratedDefaultConstructor(psiClass, methodSignature, myState.myIgnoreImplicitConstructors, myState.myIgnoreEmptyPrivateConstructors);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaCoverageOptionsProvider.State getState() {
|
||||
@@ -50,11 +74,13 @@ public class JavaCoverageOptionsProvider implements PersistentStateComponent<Jav
|
||||
@Override
|
||||
public void loadState(JavaCoverageOptionsProvider.State state) {
|
||||
myState.myIgnoreEmptyPrivateConstructors = state.myIgnoreEmptyPrivateConstructors;
|
||||
myState.myIgnoreImplicitConstructors = state.myIgnoreImplicitConstructors;
|
||||
}
|
||||
|
||||
|
||||
public static class State {
|
||||
public boolean myIgnoreEmptyPrivateConstructors = true;
|
||||
public boolean myIgnoreImplicitConstructors = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,13 +60,16 @@ public class PackageAnnotator {
|
||||
private final PsiManager myManager;
|
||||
private final CoverageDataManager myCoverageManager;
|
||||
private final boolean myIgnoreEmptyPrivateConstructors;
|
||||
private final boolean myIgnoreImplicitConstructor;
|
||||
|
||||
public PackageAnnotator(final PsiPackage aPackage) {
|
||||
myPackage = aPackage;
|
||||
myProject = myPackage.getProject();
|
||||
myManager = PsiManager.getInstance(myProject);
|
||||
myCoverageManager = CoverageDataManager.getInstance(myProject);
|
||||
myIgnoreEmptyPrivateConstructors = JavaCoverageOptionsProvider.getInstance(myProject).ignoreEmptyPrivateConstructors();
|
||||
JavaCoverageOptionsProvider optionsProvider = JavaCoverageOptionsProvider.getInstance(myProject);
|
||||
myIgnoreEmptyPrivateConstructors = optionsProvider.ignoreEmptyPrivateConstructors();
|
||||
myIgnoreImplicitConstructor = optionsProvider.ignoreImplicitConstructors();
|
||||
}
|
||||
|
||||
public interface Annotator {
|
||||
@@ -447,6 +450,10 @@ public class PackageAnnotator {
|
||||
else if (lineData.getStatus() == LineCoverage.PARTIAL) {
|
||||
toplevelClassCoverageInfo.partiallyCoveredLineCount++;
|
||||
}
|
||||
else if ((myIgnoreEmptyPrivateConstructors || myIgnoreImplicitConstructor) &&
|
||||
isGeneratedDefaultConstructor(psiClass, lineData.getMethodSignature(), myIgnoreImplicitConstructor, myIgnoreEmptyPrivateConstructors)) {
|
||||
continue;
|
||||
}
|
||||
toplevelClassCoverageInfo.totalLineCount++;
|
||||
packageCoverageInfo.totalLineCount++;
|
||||
}
|
||||
@@ -459,7 +466,8 @@ public class PackageAnnotator {
|
||||
touchedClass = true;
|
||||
}
|
||||
|
||||
if (myIgnoreEmptyPrivateConstructors && isGeneratedDefaultConstructor(psiClass, (String)nameAndSig)) {
|
||||
if ((myIgnoreEmptyPrivateConstructors || myIgnoreImplicitConstructor) &&
|
||||
isGeneratedDefaultConstructor(psiClass, (String)nameAndSig, myIgnoreImplicitConstructor, myIgnoreEmptyPrivateConstructors)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -508,24 +516,26 @@ public class PackageAnnotator {
|
||||
* Checks if the method is a default constructor generated by the compiler. Such constructors are not marked as synthetic
|
||||
* in the bytecode, so we need to look at the PSI to see if the class defines such a constructor.
|
||||
*/
|
||||
public static boolean isGeneratedDefaultConstructor(@Nullable final PsiClass aClass, String nameAndSig) {
|
||||
if (aClass == null) {
|
||||
return false;
|
||||
}
|
||||
public static boolean isGeneratedDefaultConstructor(@Nullable final PsiClass aClass, String nameAndSig,
|
||||
boolean implicitConstructor, boolean privateEmpty) {
|
||||
if (aClass == null || !implicitConstructor && !privateEmpty) return false;
|
||||
if (DEFAULT_CONSTRUCTOR_NAME_SIGNATURE.equals(nameAndSig)) {
|
||||
return hasGeneratedOrEmptyPrivateConstructor(aClass);
|
||||
return hasGeneratedOrEmptyPrivateConstructor(aClass, implicitConstructor, privateEmpty);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasGeneratedOrEmptyPrivateConstructor(@NotNull final PsiClass aClass) {
|
||||
private static boolean hasGeneratedOrEmptyPrivateConstructor(@NotNull final PsiClass aClass,
|
||||
boolean implicitConstructor,
|
||||
boolean privateEmpty) {
|
||||
return ReadAction.compute(() -> {
|
||||
PsiMethod[] constructors = aClass.getConstructors();
|
||||
if (constructors.length == 1 && constructors[0].hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (privateEmpty && constructors.length == 1 && constructors[0].hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
PsiCodeBlock body = constructors[0].getBody();
|
||||
return body != null && body.getStatements().length == 0;
|
||||
return body != null && body.getStatements().length == 0 &&
|
||||
Arrays.stream(aClass.getMethods()).allMatch(method -> method.hasModifierProperty(PsiModifier.STATIC));
|
||||
}
|
||||
return constructors.length == 0;
|
||||
return implicitConstructor && constructors.length == 0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -567,6 +577,7 @@ public class PackageAnnotator {
|
||||
if (coverageSuite == null) return false;
|
||||
return SourceLineCounterUtil
|
||||
.collectNonCoveredClassInfo(classCoverageInfo, packageCoverageInfo, content, coverageSuite.isTracingEnabled(),
|
||||
myIgnoreEmptyPrivateConstructors ? description -> !isGeneratedDefaultConstructor(psiClass, description) : Condition.TRUE);
|
||||
myIgnoreEmptyPrivateConstructors || myIgnoreImplicitConstructor
|
||||
? description -> !isGeneratedDefaultConstructor(psiClass, description, myIgnoreImplicitConstructor, myIgnoreEmptyPrivateConstructors) : Condition.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
package com.intellij.coverage;
|
||||
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.rt.coverage.instrumentation.SourceLineCounter;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
@@ -68,13 +64,7 @@ public class SourceLineCounterUtil {
|
||||
reader.accept(collector, 0);
|
||||
|
||||
String qualifiedName = reader.getClassName();
|
||||
boolean ignoreEmptyPrivateConstructors = JavaCoverageOptionsProvider.getInstance(project).ignoreEmptyPrivateConstructors();
|
||||
PsiClass psiClass = ignoreEmptyPrivateConstructors
|
||||
? ReadAction.compute(() -> ClassUtil.findPsiClassByJVMName(PsiManager.getInstance(project), qualifiedName))
|
||||
: null;
|
||||
Condition<String> includeDescriptionCondition = ignoreEmptyPrivateConstructors
|
||||
? description -> !PackageAnnotator.isGeneratedDefaultConstructor(psiClass, description)
|
||||
: Condition.TRUE;
|
||||
Condition<String> includeDescriptionCondition = description -> !JavaCoverageOptionsProvider.getInstance(project).isGeneratedConstructor(qualifiedName, description);
|
||||
TIntObjectHashMap<?> lines = collector.getSourceLines();
|
||||
lines.forEachEntry((line, description) -> {
|
||||
if (includeDescriptionCondition.value((String)description)) {
|
||||
|
||||
Reference in New Issue
Block a user