From 72e8d5b606d78aa3844905d8e19329fad1f5af0c Mon Sep 17 00:00:00 2001 From: Junichi Yamamoto Date: Sat, 22 Apr 2023 14:37:56 +0900 Subject: [PATCH] Detect the PHPUnit version --- .../modules/php/phpunit/PhpUnitVersion.java | 22 ++++ .../modules/php/phpunit/commands/PhpUnit.java | 113 +++++++++++++++++- .../phpunit/ui/customizer/Bundle.properties | 2 - .../ui/customizer/CustomizerPhpUnit.form | 24 +--- .../ui/customizer/CustomizerPhpUnit.java | 95 +++++++++++++-- .../ui/options/PhpUnitOptionsPanel.form | 56 +++++---- .../ui/options/PhpUnitOptionsPanel.java | 50 +++++--- .../PhpUnitOptionsPanelController.java | 48 +++++++- 8 files changed, 331 insertions(+), 79 deletions(-) diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/PhpUnitVersion.java b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/PhpUnitVersion.java index 7239a6295dac..da071f0380b2 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/PhpUnitVersion.java +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/PhpUnitVersion.java @@ -18,7 +18,9 @@ */ package org.netbeans.modules.php.phpunit; +import org.netbeans.api.annotations.common.NonNull; import org.openide.util.NbBundle; +import org.openide.util.Parameters; @NbBundle.Messages({ "PhpUnitVersion.PHP_UNIT_9=PHPUnit 9 or earlier", @@ -40,10 +42,30 @@ public static PhpUnitVersion getDefault() { return phpUnitVersions[0]; } + public static PhpUnitVersion fromString(@NonNull String version) { + Parameters.notNull("version", version); // NOI18N + String[] versions = version.split("\\."); // NOI18N + try { + int majorVersion = Integer.parseInt(versions[0]); + if (majorVersion >= 10) { + return PHP_UNIT_10; + } else if (majorVersion <= 9) { + return PHP_UNIT_9; + } + } catch (NumberFormatException ex) { + // no-op + } + return getDefault(); + } + public String getDisplayName() { return displayName; } + public boolean useNetBeansSuite() { + return this == PHP_UNIT_9; + } + @Override public String toString() { return getDisplayName(); diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/commands/PhpUnit.java b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/commands/PhpUnit.java index 6c2bce1cad9f..07027324defc 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/commands/PhpUnit.java +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/commands/PhpUnit.java @@ -34,12 +34,15 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.annotations.common.NullAllowed; import org.netbeans.api.extexecution.ExecutionDescriptor; import org.netbeans.api.extexecution.base.input.InputProcessor; import org.netbeans.api.extexecution.base.input.InputProcessors; @@ -75,6 +78,7 @@ import org.openide.loaders.DataObject; import org.openide.modules.InstalledFileLocator; import org.openide.util.NbBundle; +import org.openide.windows.InputOutput; /** * PHPUnit 3.4+ support. @@ -106,6 +110,7 @@ public final class PhpUnit { private static final String LIST_GROUPS_PARAM = "--list-groups"; // NOI18N private static final String GROUP_PARAM = "--group"; // NOI18N private static final String PARAM_SEPARATOR = "--"; // NOI18N + private static final String VERSION_PARAM = "--version"; // NOI18N // bootstrap & config private static final String BOOTSTRAP_PARAM = "--bootstrap"; // NOI18N private static final String BOOTSTRAP_FILENAME = "bootstrap%s.php"; // NOI18N @@ -138,6 +143,8 @@ public final class PhpUnit { // #200489 private static volatile File suite; // ok if it is fetched more times + private static final ConcurrentMap VERSIONS = new ConcurrentHashMap<>(); + private final String phpUnitPath; @@ -200,6 +207,15 @@ public static PhpUnit getForPhpModule(PhpModule phpModule, boolean showCustomize return new PhpUnit(path); } + public static void resetVersions() { + VERSIONS.clear(); + } + + public static String getVersionLine(String path) { + PhpUnit phpUnit = new PhpUnit(path); + return phpUnit.getVersionLine((PhpModule) null); + } + @CheckForNull private static String validateDefault() { ValidationResult result = new PhpUnitOptionsValidator() @@ -235,6 +251,51 @@ private static File getNbSuite() { return suite; } + @NbBundle.Messages({ + "PhpUnit.getting.phpUnit.version=Getting the version...", + "PhpUnit.notFound.phpUnit.version=PHPUnit version not found", + }) + public String getVersionLine(@NullAllowed PhpModule phpModule) { + PhpExecutable phpUnit = phpModule != null ? getExecutable(phpModule) : new PhpExecutable(phpUnitPath); + if (phpUnit != null) { + phpUnit.additionalParameters(Arrays.asList(VERSION_PARAM)); + final PhpUnitLineProcessor lineProcessor = new PhpUnitLineProcessor(); + ExecutionDescriptor silentDescriptor = getSilentDescriptor(); + PhpUnitOutputProcessorFactory outputProcessorFactory = new PhpUnitOutputProcessorFactory(lineProcessor); + try { + phpUnit.runAndWait(silentDescriptor, outputProcessorFactory, Bundle.PhpUnit_getting_phpUnit_version()); + String version = lineProcessor.getLinesAsText(); + return !version.isEmpty() ? version : Bundle.PhpUnit_notFound_phpUnit_version(); + } catch (ExecutionException ex) { + LOGGER.log(Level.INFO, null, ex); + } + } + return Bundle.PhpUnit_notFound_phpUnit_version(); + } + + private PhpUnitVersion getVersion(PhpModule phpModule) { + return getVersion(phpModule, false); + } + + private PhpUnitVersion getVersion(PhpModule phpModule, boolean force) { + PhpUnitVersion phpUnitVersion = VERSIONS.get(phpModule); + if (phpUnitVersion != null && !force) { + return phpUnitVersion; + } + String versionLine = getVersionLine(phpModule); + phpUnitVersion = getVersion(versionLine); + VERSIONS.putIfAbsent(phpModule, phpUnitVersion); + return phpUnitVersion; + } + + private PhpUnitVersion getVersion(String versionLine) { + String[] versionParts = versionLine.split(" "); // NOI18N e.g. PHPUnit 10.0.1 by ... + if (versionParts.length >= 2) { + return PhpUnitVersion.fromString(versionParts[1]); + } + return PhpUnitVersion.getDefault(); + } + @CheckForNull public Integer runTests(PhpModule phpModule, TestRunInfo runInfo) throws TestRunException { PhpExecutable phpUnit = getExecutable(phpModule); @@ -403,11 +464,12 @@ private TestParams getTestParams(PhpModule phpModule, TestRunInfo runInfo) throw // only test dir and use 'phpunit' command only useNbSuite = false; } + PhpUnitVersion version = getVersion(phpModule); if (useNbSuite) { // standard suite // #218607 - hotfix //params.add(SUITE_NAME) - if (PhpUnitPreferences.getPhpUnitVersion(phpModule) == PhpUnitVersion.PHP_UNIT_9) { + if (version.useNetBeansSuite()) { params.add(getNbSuite().getAbsolutePath()); } else { // GH-5790 we can use NetBeansSuite.php no longer with PHPUnit 10 @@ -457,6 +519,11 @@ private ExecutionDescriptor getGroupsDescriptor() { .optionsPath(PhpUnitOptionsPanelController.OPTIONS_PATH); } + private ExecutionDescriptor getSilentDescriptor() { + return new ExecutionDescriptor() + .inputOutput(InputOutput.NULL); + } + // #170120 @CheckForNull private File getWorkingDirectory(PhpModule phpModule) { @@ -792,6 +859,50 @@ public boolean hasOutput() { } + private static final class PhpUnitOutputProcessorFactory implements ExecutionDescriptor.InputProcessorFactory2 { + + private final LineProcessor lineProcessor; + + public PhpUnitOutputProcessorFactory(LineProcessor lineProcessor) { + this.lineProcessor = lineProcessor; + } + + @Override + public InputProcessor newInputProcessor(InputProcessor defaultProcessor) { + return InputProcessors.ansiStripping(InputProcessors.bridge(lineProcessor)); + } + } + + private static final class PhpUnitLineProcessor implements LineProcessor { + + private final List lines = new ArrayList<>(); + + @Override + public void processLine(String line) { + lines.add(line); + } + + @Override + public void reset() { + } + + @Override + public void close() { + } + + public List getLines() { + return Collections.unmodifiableList(lines); + } + + public String getLinesAsText() { + StringBuilder sb = new StringBuilder(); + for (String string : lines) { + sb.append(string).append("\n"); // NOI18N + } + return sb.toString().trim(); + } + } + private static final class TestParams { private final List params; diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/Bundle.properties b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/Bundle.properties index 379b65ccf2d2..982bfe189122 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/Bundle.properties +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/Bundle.properties @@ -68,6 +68,4 @@ CustomizerPhpUnit.scriptLabel.text=PHPUnit Script: CustomizerPhpUnit.scriptBrowseButton.text=Brow&se... CustomizerPhpUnit.runPhpUnitOnlyCheckBox.text=&Test Project Using Just 'phpunit' Command CustomizerPhpUnit.versionLabel.text=PHPUnit &Version: -CustomizerPhpUnit.versionComboBox.AccessibleContext.accessibleDescription=Select PHPUnit version for your project CustomizerPhpUnit.versionLabel.AccessibleContext.accessibleDescription=PHPUnit version label -CustomizerPhpUnit.versionComboBox.AccessibleContext.accessibleName=PHPUnit Version diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.form b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.form index 0156040071ff..06604e4cee8c 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.form +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.form @@ -106,7 +106,8 @@ - + + @@ -160,7 +161,7 @@ - + @@ -482,7 +483,7 @@ - + @@ -494,23 +495,10 @@ - + - - - + - - - - - - - - - - - diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.java b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.java index 9a0d42b28a05..03c5ff0adc1f 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.java +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/customizer/CustomizerPhpUnit.java @@ -20,6 +20,7 @@ package org.netbeans.modules.php.phpunit.ui.customizer; import java.awt.Component; +import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -30,19 +31,21 @@ import javax.swing.GroupLayout.Alignment; import javax.swing.JButton; import javax.swing.JCheckBox; -import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.netbeans.modules.php.api.phpmodule.PhpModule; +import org.netbeans.modules.php.api.util.StringUtils; import org.netbeans.modules.php.api.validation.ValidationResult; import org.netbeans.modules.php.phpunit.PhpUnitVersion; import org.netbeans.modules.php.phpunit.commands.PhpUnit; +import org.netbeans.modules.php.phpunit.options.PhpUnitOptions; import org.netbeans.modules.php.phpunit.preferences.PhpUnitPreferences; import org.netbeans.modules.php.phpunit.preferences.PhpUnitPreferencesValidator; import org.netbeans.spi.project.ui.support.ProjectCustomizer; @@ -54,6 +57,7 @@ import org.openide.filesystems.FileUtil; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; /** * @author Tomas Mysik @@ -61,6 +65,7 @@ public final class CustomizerPhpUnit extends JPanel implements HelpCtx.Provider { private static final long serialVersionUID = 2171421712032630826L; + private static final RequestProcessor RP = new RequestProcessor(CustomizerPhpUnit.class); private final ProjectCustomizer.Category category; private final PhpModule phpModule; @@ -141,7 +146,28 @@ void validateData() { category.setValid(true); } + void updatePhpUnitVersion() { + assert EventQueue.isDispatchThread(); + ValidationResult result = new PhpUnitPreferencesValidator() + .validatePhpUnit(scriptCheckBox.isSelected(), scriptTextField.getText()) + .getResult(); + // errors and warnings are shown with validateData() + if (result.hasErrors() || result.hasWarnings()) { + versionLineLabel.setText(Bundle.CustomizerPhpUnit_notFound_phpUnit_version()); + return; + } + setPhpUnitVersion(); + } + + private boolean resetPhpUnitVersions() { + return scriptCheckBox.isSelected() != PhpUnitPreferences.isPhpUnitEnabled(phpModule) + || (!scriptTextField.getText().equals(PhpUnitPreferences.getPhpUnitPath(phpModule))); + } + void storeData() { + if (resetPhpUnitVersions()) { + PhpUnit.resetVersions(); + } PhpUnitPreferences.setBootstrapEnabled(phpModule, bootstrapCheckBox.isSelected()); PhpUnitPreferences.setBootstrapPath(phpModule, bootstrapTextField.getText()); PhpUnitPreferences.setBootstrapForCreateTests(phpModule, bootstrapForCreateTestsCheckBox.isSelected()); @@ -154,7 +180,6 @@ void storeData() { PhpUnitPreferences.setRunPhpUnitOnly(phpModule, runPhpUnitOnlyCheckBox.isSelected()); PhpUnitPreferences.setRunAllTestFiles(phpModule, runTestUsingUnitCheckBox.isSelected()); PhpUnitPreferences.setAskForTestGroups(phpModule, askForTestGroupsCheckBox.isSelected()); - PhpUnitPreferences.setPhpUnitVersion(phpModule, (PhpUnitVersion) versionComboBox.getSelectedItem()); } private void initFile(boolean enabled, String file, JCheckBox checkBox, JTextField textField) { @@ -203,9 +228,11 @@ public void itemStateChanged(ItemEvent e) { public void itemStateChanged(ItemEvent e) { enableFile(e.getStateChange() == ItemEvent.SELECTED, scriptLabel, scriptTextField, scriptBrowseButton); validateData(); + updatePhpUnitVersion(); } }); scriptTextField.getDocument().addDocumentListener(defaultDocumentListener); + scriptTextField.getDocument().addDocumentListener(new PhpUnitScriptDocumentListener()); final ItemListener validateItemListener = new ItemListener() { @Override @@ -242,9 +269,30 @@ private boolean checkTestDirectory() { } private void initPhpUnitVersion() { - PhpUnitVersion phpVersion = PhpUnitPreferences.getPhpUnitVersion(phpModule); - assert phpVersion != null; - versionComboBox.setModel(new PhpUnitVersionComboBoxModel(phpVersion)); + setPhpUnitVersion(); + } + + @NbBundle.Messages({ + "CustomizerPhpUnit.getting.phpUnit.version=Getting the version...", + "CustomizerPhpUnit.notFound.phpUnit.version=PHPUnit version not found" + }) + private void setPhpUnitVersion() { + assert EventQueue.isDispatchThread(); + versionLineLabel.setText(Bundle.CustomizerPhpUnit_getting_phpUnit_version()); + final String phpUnitPath; + if (scriptCheckBox.isSelected()) { + phpUnitPath = scriptTextField.getText().trim(); + } else { + phpUnitPath = PhpUnitOptions.getInstance().getPhpUnitPath(); + } + if (!StringUtils.hasText(phpUnitPath)) { + SwingUtilities.invokeLater(() -> versionLineLabel.setText(Bundle.CustomizerPhpUnit_notFound_phpUnit_version())); + } else { + RP.post(() -> { + String versionLine = PhpUnit.getVersionLine(phpUnitPath); + SwingUtilities.invokeLater(() -> versionLineLabel.setText(versionLine)); + }); + } } /** This method is called from within the constructor to @@ -280,7 +328,7 @@ private void initComponents() { runTestUsingUnitCheckBox = new JCheckBox(); askForTestGroupsCheckBox = new JCheckBox(); versionLabel = new JLabel(); - versionComboBox = new JComboBox<>(); + versionLineLabel = new JLabel(); bootstrapLabel.setLabelFor(bootstrapTextField); Mnemonics.setLocalizedText(bootstrapLabel, NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.bootstrapLabel.text")); // NOI18N @@ -362,9 +410,10 @@ public void actionPerformed(ActionEvent evt) { Mnemonics.setLocalizedText(askForTestGroupsCheckBox, NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.askForTestGroupsCheckBox.text")); // NOI18N - versionLabel.setLabelFor(versionComboBox); Mnemonics.setLocalizedText(versionLabel, NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.versionLabel.text")); // NOI18N + Mnemonics.setLocalizedText(versionLineLabel, "VERSION"); // NOI18N + GroupLayout layout = new GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING) @@ -420,7 +469,8 @@ public void actionPerformed(ActionEvent evt) { .addGroup(layout.createSequentialGroup() .addComponent(versionLabel) .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(versionComboBox, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(versionLineLabel) + .addGap(0, 0, Short.MAX_VALUE)) ); layout.linkSize(SwingConstants.HORIZONTAL, new Component[] {bootstrapBrowseButton, bootstrapGenerateButton, configurationBrowseButton, configurationGenerateButton, scriptBrowseButton, suiteBrowseButton}); @@ -470,7 +520,7 @@ public void actionPerformed(ActionEvent evt) { .addPreferredGap(ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(versionLabel) - .addComponent(versionComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addComponent(versionLineLabel)) .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -507,8 +557,6 @@ public void actionPerformed(ActionEvent evt) { suiteInfoLabel.getAccessibleContext().setAccessibleName(NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.suiteInfoLabel.AccessibleContext.accessibleName")); // NOI18N suiteInfoLabel.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.suiteInfoLabel.AccessibleContext.accessibleDescription")); // NOI18N versionLabel.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.versionLabel.AccessibleContext.accessibleDescription")); // NOI18N - versionComboBox.getAccessibleContext().setAccessibleName(NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.versionComboBox.AccessibleContext.accessibleName")); // NOI18N - versionComboBox.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.versionComboBox.AccessibleContext.accessibleDescription")); // NOI18N getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CustomizerPhpUnit.class, "CustomizerPhpUnit.AccessibleContext.accessibleDescription")); // NOI18N }// //GEN-END:initComponents @@ -608,8 +656,8 @@ private void scriptBrowseButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:eve private JLabel suiteInfoLabel; private JLabel suiteLabel; private JTextField suiteTextField; - private JComboBox versionComboBox; private JLabel versionLabel; + private JLabel versionLineLabel; // End of variables declaration//GEN-END:variables //~ Inner classes @@ -632,6 +680,29 @@ private void processUpdate() { } } + private final class PhpUnitScriptDocumentListener implements DocumentListener { + + @Override + public void insertUpdate(DocumentEvent e) { + processUpdate(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + processUpdate(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + processUpdate(); + } + + private void processUpdate() { + updatePhpUnitVersion(); + } + } + + // if we have to add the phpunit version combobox in the future, we can use this private static class PhpUnitVersionComboBoxModel extends DefaultComboBoxModel { private static final long serialVersionUID = 5850175934190021687L; diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.form b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.form index 22a03bc88763..05d6cf4c2a8a 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.form +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.form @@ -45,6 +45,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -73,6 +96,7 @@ + @@ -80,29 +104,6 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -115,8 +116,10 @@ + + - + @@ -380,5 +383,10 @@ + + + + + diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.java b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.java index 65644dbdaea0..3baa747f8a43 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.java +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanel.java @@ -85,6 +85,7 @@ public PhpUnitOptionsPanel() { }) private void init() { errorLabel.setText(" "); // NOI18N + phpUnitVersionLabel.setText(" "); // NOI18N phpUnitHintLabel.setText(Bundle.PhpUnitOptionsPanel_phpUnit_hint( PhpUnit.SCRIPT_NAME, PhpUnit.SCRIPT_NAME_LONG, PhpUnit.SCRIPT_NAME_PHAR)); skelGenHintLabel.setText(Bundle.PhpUnitOptionsPanel_skelGen_hint( @@ -123,6 +124,10 @@ public void setWarning(String message) { errorLabel.setText(message); } + public void setVersion(String version) { + phpUnitVersionLabel.setText(version); + } + public void addChangeListener(ChangeListener listener) { changeSupport.addChangeListener(listener); } @@ -163,6 +168,7 @@ private void initComponents() { phpUnitLearnMoreLabel = new JLabel(); skelGenLearnMoreLabel = new JLabel(); errorLabel = new JLabel(); + phpUnitVersionLabel = new JLabel(); phpUnitLabel.setLabelFor(phpUnitBrowseButton); Mnemonics.setLocalizedText(phpUnitLabel, NbBundle.getMessage(PhpUnitOptionsPanel.class, "PhpUnitOptionsPanel.phpUnitLabel.text")); // NOI18N @@ -236,9 +242,29 @@ public void mousePressed(MouseEvent evt) { Mnemonics.setLocalizedText(errorLabel, "ERROR"); // NOI18N + Mnemonics.setLocalizedText(phpUnitVersionLabel, "VERSION"); // NOI18N + GroupLayout layout = new GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(errorLabel) + .addComponent(noteLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(phpUnitInfoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(phpUnitPhp53InfoLabel) + .addComponent(installationInfoLabel) + .addComponent(phpUnitLearnMoreLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(skelGenLearnMoreLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(phpUnit370InfoLabel)))) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(skelGenAbandonedLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.LEADING) .addComponent(phpUnitLabel) @@ -261,27 +287,10 @@ public void mousePressed(MouseEvent evt) { .addComponent(skelGenSearchButton)))) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(phpUnitVersionLabel) .addComponent(skelGenHintLabel) .addComponent(phpUnitHintLabel)) .addGap(0, 0, Short.MAX_VALUE)))) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(Alignment.LEADING) - .addComponent(errorLabel) - .addComponent(noteLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(Alignment.LEADING) - .addComponent(phpUnitInfoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(phpUnitPhp53InfoLabel) - .addComponent(installationInfoLabel) - .addComponent(phpUnitLearnMoreLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(skelGenLearnMoreLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addComponent(phpUnit370InfoLabel)))) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(skelGenAbandonedLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.linkSize(SwingConstants.HORIZONTAL, new Component[] {phpUnitBrowseButton, phpUnitSearchButton, skelGenBrowseButton, skelGenSearchButton}); @@ -294,8 +303,10 @@ public void mousePressed(MouseEvent evt) { .addComponent(phpUnitSearchButton) .addComponent(phpUnitBrowseButton)) .addPreferredGap(ComponentPlacement.RELATED) - .addComponent(phpUnitHintLabel) + .addComponent(phpUnitVersionLabel) .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(phpUnitHintLabel) + .addPreferredGap(ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(skelGenTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(skelGenLabel) @@ -488,6 +499,7 @@ public String getNoItemsFound() { private JLabel phpUnitPhp53InfoLabel; private JButton phpUnitSearchButton; private JTextField phpUnitTextField; + private JLabel phpUnitVersionLabel; private JLabel skelGenAbandonedLabel; private JButton skelGenBrowseButton; private JLabel skelGenHintLabel; diff --git a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanelController.java b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanelController.java index a29280df6633..c5138e15c137 100644 --- a/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanelController.java +++ b/php/php.phpunit/src/org/netbeans/modules/php/phpunit/ui/options/PhpUnitOptionsPanelController.java @@ -26,14 +26,18 @@ import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.netbeans.modules.php.api.util.StringUtils; import org.netbeans.modules.php.api.util.UiUtils; import org.netbeans.modules.php.api.validation.ValidationResult; +import org.netbeans.modules.php.phpunit.commands.PhpUnit; import org.netbeans.modules.php.phpunit.commands.SkeletonGenerator; import org.netbeans.modules.php.phpunit.options.PhpUnitOptions; import org.netbeans.modules.php.phpunit.options.PhpUnitOptionsValidator; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.HelpCtx; import org.openide.util.Lookup; +import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; @UiUtils.PhpOptionsPanelRegistration( id=PhpUnitOptionsPanelController.ID, @@ -48,11 +52,14 @@ public class PhpUnitOptionsPanelController extends OptionsPanelController implem public static final String OPTIONS_PATH = UiUtils.OPTIONS_PATH + "/" + OPTIONS_SUB_PATH; // NOI18N private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + private static final RequestProcessor RP = new RequestProcessor(PhpUnitOptionsPanelController.class); // @GuardedBy("EDT") private PhpUnitOptionsPanel phpUnitOptionsPanel = null; private volatile boolean changed = false; private boolean firstOpening = true; + private String previousPhpUnitPath; + private String previousSkeletonGeneratorPath; @Override @@ -62,6 +69,7 @@ public void update() { firstOpening = false; getPhpUnitOptionsPanel().setPhpUnit(getPhpUnitOptions().getPhpUnitPath()); getPhpUnitOptionsPanel().setPhpUnitSkelGen(getPhpUnitOptions().getSkeletonGeneratorPath()); + updatePhpUnitVersion(); } changed = false; @@ -76,7 +84,7 @@ public void run() { getPhpUnitOptions().setPhpUnitPath(getPhpUnitOptionsPanel().getPhpUnit()); getPhpUnitOptions().setSkeletonGeneratorPath(getPhpUnitOptionsPanel().getPhpUnitSkelGen()); - + PhpUnit.resetVersions(); changed = false; } }); @@ -93,6 +101,7 @@ public void cancel() { @Override public boolean isValid() { assert EventQueue.isDispatchThread(); + setPhpUnitVersion(); PhpUnitOptionsPanel panel = getPhpUnitOptionsPanel(); ValidationResult result = new PhpUnitOptionsValidator() .validate(panel.getPhpUnit(), panel.getPhpUnitSkelGen()) @@ -112,15 +121,48 @@ public boolean isValid() { return true; } + @NbBundle.Messages({ + "PhpUnitOptionsPanelController.getting.phpUnit.version=Getting the version...", + "PhpUnitOptionsPanelController.notFound.phpUnit.version=PHPUnit version not found" + }) + private void updatePhpUnitVersion() { + String phpUnitPath = getPhpUnitOptionsPanel().getPhpUnit(); + if (!StringUtils.hasText(phpUnitPath)) { + SwingUtilities.invokeLater(() -> getPhpUnitOptionsPanel().setVersion(Bundle.PhpUnitOptionsPanelController_notFound_phpUnit_version())); + return; + } + SwingUtilities.invokeLater(() -> getPhpUnitOptionsPanel().setVersion(Bundle.PhpUnitOptionsPanelController_getting_phpUnit_version())); + RP.post(() -> { + String versionLine = PhpUnit.getVersionLine(phpUnitPath); + SwingUtilities.invokeLater(() -> getPhpUnitOptionsPanel().setVersion(versionLine)); + }); + } + + private void setPhpUnitVersion() { + PhpUnitOptionsPanel panel = getPhpUnitOptionsPanel(); + ValidationResult phpUnitPathResult = new PhpUnitOptionsValidator() + .validatePhpUnitPath(panel.getPhpUnit()) + .getResult(); + if (!phpUnitPathResult.hasErrors() && !phpUnitPathResult.hasWarnings()) { + updatePhpUnitVersion(); + } else { + panel.setVersion(Bundle.PhpUnitOptionsPanelController_notFound_phpUnit_version()); + } + } + @Override public boolean isChanged() { - String saved = getPhpUnitOptions().getPhpUnitPath(); + // to avoid calling isValid() infinitely + // use the previous path as a saved path instead of getPhpUnitOptions().getPhpUnitPath(); + String saved = previousPhpUnitPath; String current = getPhpUnitOptionsPanel().getPhpUnit().trim(); + previousPhpUnitPath = current; if(saved == null ? !current.isEmpty() : !saved.equals(current)) { return true; } - saved = getPhpUnitOptions().getSkeletonGeneratorPath(); + saved = previousSkeletonGeneratorPath; current = getPhpUnitOptionsPanel().getPhpUnitSkelGen().trim(); + previousSkeletonGeneratorPath = current; return saved == null ? !current.isEmpty() : !saved.equals(current); }