| /* |
| * Copyright 2000-2007 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.configurations.coverage; |
| |
| import com.intellij.codeInsight.CodeInsightBundle; |
| import com.intellij.coverage.CoverageRunner; |
| import com.intellij.coverage.JavaCoverageEngine; |
| import com.intellij.execution.CommonJavaRunConfigurationParameters; |
| import com.intellij.execution.ExecutionBundle; |
| import com.intellij.execution.configurations.ModuleBasedConfiguration; |
| import com.intellij.execution.configurations.RunConfigurationBase; |
| import com.intellij.execution.util.JreVersionDetector; |
| import com.intellij.icons.AllIcons; |
| import com.intellij.ide.util.ClassFilter; |
| import com.intellij.ide.util.PackageChooserDialog; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.extensions.Extensions; |
| import com.intellij.openapi.options.ConfigurationException; |
| import com.intellij.openapi.options.SettingsEditor; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.PackageChooser; |
| import com.intellij.openapi.ui.VerticalFlowLayout; |
| import com.intellij.psi.PsiClass; |
| import com.intellij.psi.PsiPackage; |
| import com.intellij.ui.IdeBorderFactory; |
| import com.intellij.ui.ListCellRendererWrapper; |
| import com.intellij.ui.classFilter.ClassFilterEditor; |
| import com.intellij.util.IconUtil; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.util.List; |
| |
| /** |
| * Base {@link com.intellij.openapi.options.Configurable} for configuring code coverage |
| * To obtain a full configurable use |
| * <code> |
| * SettingsEditorGroup<YourConfiguration> group = new SettingsEditorGroup<YourConfiguration>(); |
| * group.addEditor(title, yourConfigurable); |
| * group.addEditor(title, yourCoverageConfigurable); |
| * </code> |
| * @author ven |
| */ |
| public class CoverageConfigurable extends SettingsEditor<RunConfigurationBase> { |
| private static final Logger LOG = Logger.getInstance("#" + CoverageConfigurable.class.getName()); |
| |
| private final JreVersionDetector myVersionDetector = new JreVersionDetector(); |
| Project myProject; |
| private MyClassFilterEditor myClassFilterEditor; |
| private JLabel myCoverageNotSupportedLabel; |
| private JComboBox myCoverageRunnerCb; |
| private JPanel myRunnerPanel; |
| private JCheckBox myTrackPerTestCoverageCb; |
| private JCheckBox myTrackTestSourcesCb; |
| |
| private JRadioButton myTracingRb; |
| private JRadioButton mySamplingRb; |
| private final RunConfigurationBase myConfig; |
| |
| private static class MyClassFilterEditor extends ClassFilterEditor { |
| public MyClassFilterEditor(Project project) { |
| super(project, new ClassFilter() { |
| public boolean isAccepted(PsiClass aClass) { |
| if (aClass.getContainingClass() != null) return false; |
| return true; |
| } |
| }); |
| } |
| |
| protected void addPatternFilter() { |
| PackageChooser chooser = new PackageChooserDialog(CodeInsightBundle.message("coverage.pattern.filter.editor.choose.package.title"), myProject); |
| chooser.show(); |
| if (chooser.isOK()) { |
| List<PsiPackage> packages = chooser.getSelectedPackages(); |
| if (!packages.isEmpty()) { |
| for (final PsiPackage aPackage : packages) { |
| final String fqName = aPackage.getQualifiedName(); |
| final String pattern = fqName.length() > 0 ? fqName + ".*" : "*"; |
| myTableModel.addRow(createFilter(pattern)); |
| } |
| int row = myTableModel.getRowCount() - 1; |
| myTable.getSelectionModel().setSelectionInterval(row, row); |
| myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true)); |
| myTable.requestFocus(); |
| } |
| } |
| } |
| |
| protected String getAddPatternButtonText() { |
| return CodeInsightBundle.message("coverage.button.add.package"); |
| } |
| |
| @Override |
| protected Icon getAddPatternButtonIcon() { |
| return IconUtil.getAddPackageIcon(); |
| } |
| } |
| |
| public CoverageConfigurable(RunConfigurationBase config) { |
| myConfig = config; |
| myProject = config.getProject(); |
| } |
| |
| protected void resetEditorFrom(final RunConfigurationBase runConfiguration) { |
| final boolean isJre50; |
| if (runConfiguration instanceof CommonJavaRunConfigurationParameters && myVersionDetector.isJre50Configured((CommonJavaRunConfigurationParameters)runConfiguration)) { |
| isJre50 = true; |
| } else if (runConfiguration instanceof ModuleBasedConfiguration){ |
| isJre50 = myVersionDetector.isModuleJre50Configured((ModuleBasedConfiguration)runConfiguration); |
| } else { |
| isJre50 = true; |
| } |
| |
| myCoverageNotSupportedLabel.setVisible(!isJre50); |
| |
| final JavaCoverageEnabledConfiguration configuration = (JavaCoverageEnabledConfiguration)CoverageEnabledConfiguration.getOrCreate(runConfiguration); |
| CoverageRunner runner = configuration.getCoverageRunner(); |
| if (runner != null) { |
| myCoverageRunnerCb.setSelectedItem(new CoverageRunnerItem(runner)); |
| } else { |
| final String runnerId = configuration.getRunnerId(); |
| if (runnerId != null){ |
| final CoverageRunnerItem runnerItem = new CoverageRunnerItem(runnerId); |
| final DefaultComboBoxModel model = (DefaultComboBoxModel)myCoverageRunnerCb.getModel(); |
| if (model.getIndexOf(runnerItem) == -1) { |
| model.addElement(runnerItem); |
| } |
| myCoverageRunnerCb.setSelectedItem(runnerItem); |
| } else { |
| myCoverageRunnerCb.setSelectedIndex(0); |
| } |
| runner = ((CoverageRunnerItem)myCoverageRunnerCb.getSelectedItem()).getRunner(); |
| } |
| UIUtil.setEnabled(myRunnerPanel, isJre50, true); |
| |
| |
| myClassFilterEditor.setFilters(configuration.getCoveragePatterns()); |
| final boolean isCoverageByTestApplicable = runner != null && runner.isCoverageByTestApplicable(); |
| myTracingRb.setEnabled(myTracingRb.isEnabled() && isCoverageByTestApplicable); |
| mySamplingRb.setSelected(configuration.isSampling() || !isCoverageByTestApplicable); |
| myTracingRb.setSelected(!mySamplingRb.isSelected()); |
| |
| myTrackPerTestCoverageCb.setSelected(configuration.isTrackPerTestCoverage()); |
| myTrackPerTestCoverageCb.setEnabled(myTracingRb.isEnabled() && myTracingRb.isSelected() && canHavePerTestCoverage()); |
| |
| myTrackTestSourcesCb.setSelected(configuration.isTrackTestFolders()); |
| } |
| |
| protected boolean canHavePerTestCoverage() { |
| return CoverageEnabledConfiguration.getOrCreate(myConfig).canHavePerTestCoverage(); |
| } |
| |
| protected void applyEditorTo(final RunConfigurationBase runConfiguration) throws ConfigurationException { |
| final JavaCoverageEnabledConfiguration configuration = (JavaCoverageEnabledConfiguration)CoverageEnabledConfiguration.getOrCreate(runConfiguration); |
| configuration.setCoveragePatterns(myClassFilterEditor.getFilters()); |
| configuration.setCoverageRunner(getSelectedRunner()); |
| configuration.setTrackPerTestCoverage(myTrackPerTestCoverageCb.isSelected()); |
| configuration.setSampling(mySamplingRb.isSelected()); |
| configuration.setTrackTestFolders(myTrackTestSourcesCb.isSelected()); |
| } |
| |
| @NotNull |
| protected JComponent createEditor() { |
| JPanel result = new JPanel(new GridBagLayout()); |
| |
| final DefaultComboBoxModel runnersModel = new DefaultComboBoxModel(); |
| myCoverageRunnerCb = new JComboBox(runnersModel); |
| |
| final JavaCoverageEnabledConfiguration javaCoverageEnabledConfiguration = JavaCoverageEnabledConfiguration.getFrom(myConfig); |
| LOG.assertTrue(javaCoverageEnabledConfiguration != null); |
| final JavaCoverageEngine provider = javaCoverageEnabledConfiguration.getCoverageProvider(); |
| for (CoverageRunner runner : Extensions.getExtensions(CoverageRunner.EP_NAME)) { |
| if (runner.acceptsCoverageEngine(provider)) { |
| runnersModel.addElement(new CoverageRunnerItem(runner)); |
| } |
| } |
| myCoverageRunnerCb.setRenderer(new ListCellRendererWrapper<CoverageRunnerItem>() { |
| @Override |
| public void customize(JList list, CoverageRunnerItem value, int index, boolean selected, boolean hasFocus) { |
| if (value != null) { |
| setText(value.getPresentableName()); |
| } |
| } |
| }); |
| myCoverageRunnerCb.addActionListener(new ActionListener() { |
| public void actionPerformed(final ActionEvent e) { |
| final CoverageRunner runner = getSelectedRunner(); |
| enableTracingPanel(runner != null && runner.isCoverageByTestApplicable()); |
| myTrackPerTestCoverageCb.setEnabled(myTracingRb.isSelected() && canHavePerTestCoverage() && runner != null && runner.isCoverageByTestApplicable()); |
| } |
| }); |
| myRunnerPanel = new JPanel(new GridBagLayout()); |
| myRunnerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); |
| myRunnerPanel.add(new JLabel("Choose coverage runner:"), new GridBagConstraints(0, 0, 1, 1, 0, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,10), 0, 0)); |
| myRunnerPanel.add(myCoverageRunnerCb, new GridBagConstraints(1, 0, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0)); |
| final JPanel cPanel = new JPanel(new VerticalFlowLayout()); |
| |
| mySamplingRb = new JRadioButton("Sampling"); |
| cPanel.add(mySamplingRb); |
| myTracingRb = new JRadioButton("Tracing"); |
| cPanel.add(myTracingRb); |
| |
| final ButtonGroup group = new ButtonGroup(); |
| group.add(mySamplingRb); |
| group.add(myTracingRb); |
| |
| ActionListener samplingListener = new ActionListener() { |
| public void actionPerformed(final ActionEvent e) { |
| final CoverageRunner runner = getSelectedRunner(); |
| myTrackPerTestCoverageCb.setEnabled(canHavePerTestCoverage() && myTracingRb.isSelected() && runner != null && runner.isCoverageByTestApplicable()); |
| } |
| }; |
| |
| mySamplingRb.addActionListener(samplingListener); |
| myTracingRb.addActionListener(samplingListener); |
| |
| myTrackPerTestCoverageCb = new JCheckBox("Track per test coverage"); |
| final JPanel tracingPanel = new JPanel(new BorderLayout()); |
| tracingPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); |
| tracingPanel.add(myTrackPerTestCoverageCb, BorderLayout.CENTER); |
| cPanel.add(tracingPanel); |
| myRunnerPanel.add(cPanel, new GridBagConstraints(0, 1, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0)); |
| |
| final GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE, |
| 1, 1, 1, 0, |
| GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, |
| new Insets(0, 0, 0, 0), 0, 0); |
| result.add(myRunnerPanel, gc); |
| |
| JPanel panel = new JPanel(new GridBagLayout()); |
| panel.setBorder(IdeBorderFactory.createTitledBorder(ExecutionBundle.message("record.coverage.filters.title"), false)); |
| myClassFilterEditor = new MyClassFilterEditor(myProject); |
| final GridBagConstraints bagConstraints = |
| new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, |
| new Insets(0, 0, 0, 0), 0, 0); |
| panel.add(myClassFilterEditor, bagConstraints); |
| |
| bagConstraints.weighty = 0; |
| myTrackTestSourcesCb = new JCheckBox("Enable coverage in test folders"); |
| panel.add(myTrackTestSourcesCb, bagConstraints); |
| |
| result.add(panel, gc); |
| |
| myCoverageNotSupportedLabel = new JLabel(CodeInsightBundle.message("code.coverage.is.not.supported")); |
| myCoverageNotSupportedLabel.setIcon(AllIcons.General.WarningDialog); |
| result.add(myCoverageNotSupportedLabel, gc); |
| return result; |
| } |
| |
| @Nullable |
| private CoverageRunner getSelectedRunner() { |
| final CoverageRunnerItem runnerItem = (CoverageRunnerItem)myCoverageRunnerCb.getSelectedItem(); |
| if (runnerItem == null) { |
| LOG.debug("Available runners: " + myCoverageRunnerCb.getModel().getSize()); |
| } |
| return runnerItem != null ? runnerItem.getRunner() : null; |
| } |
| |
| private void enableTracingPanel(final boolean enabled) { |
| myTracingRb.setEnabled(enabled); |
| if (!enabled) { |
| mySamplingRb.setSelected(true); |
| } |
| } |
| |
| private static class CoverageRunnerItem { |
| private CoverageRunner myRunner; |
| private @NotNull String myRunnerId; |
| |
| private CoverageRunnerItem(@NotNull CoverageRunner runner) { |
| myRunner = runner; |
| myRunnerId = runner.getId(); |
| } |
| |
| private CoverageRunnerItem(String runnerId) { |
| myRunnerId = runnerId; |
| } |
| |
| public CoverageRunner getRunner() { |
| return myRunner; |
| } |
| |
| public String getRunnerId() { |
| return myRunnerId; |
| } |
| |
| public String getPresentableName() { |
| return myRunner != null ? myRunner.getPresentableName() : myRunnerId; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| |
| CoverageRunnerItem that = (CoverageRunnerItem)o; |
| |
| if (!myRunnerId.equals(that.myRunnerId)) return false; |
| |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| return myRunnerId.hashCode(); |
| } |
| } |
| } |