From 6310f05bebe62d57977db3a7de8efb0f20fa04a3 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Fri, 17 Apr 2026 11:30:58 +0530 Subject: [PATCH 1/6] AST-101305: Disable Branch and Scan dropdown when no project is selected - Add FocusListener to project combo viewer - When user clears project and clicks outside, branch combo is disabled - Resets currentProjectId to empty when project field is cleared - Preserves existing behavior for all other scenarios Co-Authored-By: Claude Haiku 4.5 --- .../eclipse/views/CheckmarxView.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java index 43c16a4..7a78108 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java @@ -41,6 +41,8 @@ import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; @@ -904,7 +906,26 @@ protected IStatus run(IProgressMonitor monitor) { debounceTimer.schedule(pendingSearchTask, DEBOUNCE_DELAY_MS); } - }); + }); + + // Add FocusListener to disable branch combo when project is cleared and focus lost + projectComboViewer.getCombo().addFocusListener(new FocusListener() { + @Override + public void focusLost(FocusEvent e) { + // When user clicks outside project combo, check if project is empty + String enteredProject = projectComboViewer.getCombo().getText().trim(); + // If project field is empty or contains only the placeholder text, disable branch combo + if (enteredProject.isEmpty() || enteredProject.equals(PROJECT_COMBO_VIEWER_TEXT)) { + currentProjectId = PluginConstants.EMPTY_STRING; + PluginUtils.enableComboViewer(branchComboViewer, false); + } + } + + @Override + public void focusGained(FocusEvent e) { + // No action needed on focus gain + } + }); } /** From 644dae9093cb13b404b273e13db21772287bd2c8 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Mon, 20 Apr 2026 10:47:29 +0530 Subject: [PATCH 2/6] Fix: Route authentication logs to Eclipse Error Log (AST-136023) (#244) * Fix AST-136023: Route authentication logs to Eclipse Error Log Replace SLF4J log calls in Authenticator.doAuthentication() with CxLogger so auth success/failure messages appear in .metadata/.log and the Eclipse Error Log UI instead of being silently dropped. Co-Authored-By: Claude Sonnet 4.6 (1M context) * Fix AST-136023: Update unit tests to verify CxLogger static calls Replace SLF4J mockLogger verification with MockedStatic to match the updated Authenticator.doAuthentication() which now routes log output through CxLogger instead of the SLF4J instance. Co-Authored-By: Claude Sonnet 4.6 (1M context) * Refactor AST-136023: Use String.format for authentication status log message Replace string concatenation (AUTH_STATUS + cxValidateOutput) with String.format(PluginConstants.INFO_AUTHENTICATION_STATUS, cxValidateOutput) to be consistent with the error logging pattern. Updated the unit test assertion to verify the formatted string accordingly. Co-Authored-By: Claude Sonnet 4.6 (1M context) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- .../tests/unit/runner/AuthenticatorTest.java | 40 +++++++++++-------- .../eclipse/runner/Authenticator.java | 4 +- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java index 740e12a..3df473f 100644 --- a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java +++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java @@ -7,12 +7,14 @@ import org.junit.jupiter.api.Test; import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.slf4j.Logger; import com.checkmarx.ast.wrapper.CxException; import com.checkmarx.ast.wrapper.CxWrapper; import com.checkmarx.eclipse.runner.Authenticator; +import com.checkmarx.eclipse.utils.CxLogger; import com.checkmarx.eclipse.utils.PluginConstants; class AuthenticatorTest { @@ -24,14 +26,15 @@ void testDoAuthenticationSuccess() throws Exception { try (MockedConstruction mocked = Mockito.mockConstruction(CxWrapper.class, - (mock, context) -> when(mock.authValidate()).thenReturn("SUCCESS"))) { + (mock, context) -> when(mock.authValidate()).thenReturn("SUCCESS")); + MockedStatic mockedCxLogger = Mockito.mockStatic(CxLogger.class)) { Authenticator authenticator = new Authenticator(mockLogger); String result = authenticator.doAuthentication("dummyKey", "--param"); assertEquals("SUCCESS", result); - verify(mockLogger).info("Authentication Status: SUCCESS"); + mockedCxLogger.verify(() -> CxLogger.info(String.format(PluginConstants.INFO_AUTHENTICATION_STATUS, "SUCCESS"))); } } @@ -43,17 +46,18 @@ void testDoAuthenticationIOException() throws Exception { try (MockedConstruction mocked = Mockito.mockConstruction(CxWrapper.class, (mock, context) -> when(mock.authValidate()) - .thenThrow(new IOException("IO error")))) { + .thenThrow(new IOException("IO error"))); + MockedStatic mockedCxLogger = Mockito.mockStatic(CxLogger.class)) { Authenticator authenticator = new Authenticator(mockLogger); String result = authenticator.doAuthentication("dummyKey", "--param"); assertEquals("IO error", result); - verify(mockLogger).error( - eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "IO error")), - any(IOException.class) - ); + mockedCxLogger.verify(() -> CxLogger.error( + eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "IO error")), + any(IOException.class) + )); } } @@ -65,17 +69,18 @@ void testDoAuthenticationInterruptedException() throws Exception { try (MockedConstruction mocked = Mockito.mockConstruction(CxWrapper.class, (mock, context) -> when(mock.authValidate()) - .thenThrow(new InterruptedException("Interrupted")))) { + .thenThrow(new InterruptedException("Interrupted"))); + MockedStatic mockedCxLogger = Mockito.mockStatic(CxLogger.class)) { Authenticator authenticator = new Authenticator(mockLogger); String result = authenticator.doAuthentication("dummyKey", "--param"); assertEquals("Interrupted", result); - verify(mockLogger).error( - eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "Interrupted")), - any(InterruptedException.class) - ); + mockedCxLogger.verify(() -> CxLogger.error( + eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "Interrupted")), + any(InterruptedException.class) + )); } } @@ -87,17 +92,18 @@ void testDoAuthenticationCxException() throws Exception { try (MockedConstruction mocked = Mockito.mockConstruction(CxWrapper.class, (mock, context) -> when(mock.authValidate()) - .thenThrow(new CxException(1, "Cx error")))) { + .thenThrow(new CxException(1, "Cx error"))); + MockedStatic mockedCxLogger = Mockito.mockStatic(CxLogger.class)) { Authenticator authenticator = new Authenticator(mockLogger); String result = authenticator.doAuthentication("dummyKey", "--param"); assertEquals("Cx error", result); - verify(mockLogger).error( - eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "Cx error")), - any(CxException.class) - ); + mockedCxLogger.verify(() -> CxLogger.error( + eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "Cx error")), + any(CxException.class) + )); } } diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/runner/Authenticator.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/runner/Authenticator.java index 9484950..202baa9 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/runner/Authenticator.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/runner/Authenticator.java @@ -33,10 +33,10 @@ public String doAuthentication(String apiKey, String additionalParams) { try { CxWrapper wrapper = new CxWrapper(config, log); String cxValidateOutput = wrapper.authValidate(); - log.info(AUTH_STATUS + cxValidateOutput); + CxLogger.info(String.format(PluginConstants.INFO_AUTHENTICATION_STATUS, cxValidateOutput)); return cxValidateOutput; } catch (IOException | InterruptedException | CxException e) { - log.error(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, e.getMessage()), e); + CxLogger.error(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, e.getMessage()), e); return e.getMessage(); } } From 0260961ae7217622303a2e98f61d7b7f037060e6 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Mon, 20 Apr 2026 10:48:20 +0530 Subject: [PATCH 3/6] Fix: Clear detail panels on severity filter change (AST-136035) (#245) * Fix AST-136035: Clear detail panels on severity filter change; fix scan ID combo overflow - Hide resultViewComposite and attackVectorCompositePanel when filter changes so the description and attack vector windows no longer show stale content - Replace fixed widthHint=520 on scan ID combo with SWT.FILL/grabExcess layout so the combo is always visible without needing to maximize the window Co-Authored-By: Claude Sonnet 4.6 (1M context) * Fix AST-136035: Clear right panels only when displayed item's severity is filtered out Previously, toggling any severity filter always hid the description and attack vector panels. Now the panels are only cleared when the currently displayed item belongs to a severity that was just disabled. If the item's severity is still active, the panels stay visible. Co-Authored-By: Claude Sonnet 4.6 (1M context) * Fix AST-136035: Preserve tree expansion state when severity filter changes - Capture expanded elements before clearing the model so the snapshot is accurate when restoring after refresh - Pass expand=true for FILTER_CHANGED (keep GET_RESULTS at false) so previously expanded group nodes are restored after filtering instead of collapsing the entire tree Co-Authored-By: Claude Sonnet 4.6 (1M context) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- .../checkmarx/eclipse/views/CheckmarxView.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java index 43c16a4..b28a751 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java @@ -160,6 +160,7 @@ public class CheckmarxView extends ViewPart implements EventHandler { private Text commentText; private DisplayModel rootModel; private String selectedSeverity, selectedState; + private DisplayModel currentlyDisplayedItem; private Button triageButton; private SelectionAdapter triageButtonAdapter, codeBashingAdapter; private Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); @@ -1082,8 +1083,7 @@ private void createScanIdComboBox(Composite parent) { scanIdComboViewer.setContentProvider(ArrayContentProvider.getInstance()); scanIdComboViewer.setInput(new ArrayList<>()); - GridData gridData = new GridData(); - gridData.widthHint = 520; + GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false); scanIdComboViewer.getCombo().setLayoutData(gridData); scanIdComboViewer.getCombo().addListener(SWT.DefaultSelection, new Listener() { @@ -1386,6 +1386,7 @@ protected IStatus run(IProgressMonitor arg0) { if (selectedItem.getResult() != null && selectedItem.getResult().getSimilarityId() != null) { sync.asyncExec(() -> { + currentlyDisplayedItem = selectedItem; createTriageSeverityAndStateCombos(selectedItem); populateTriageChanges(selectedItem); resultViewComposite.setVisible(true); @@ -2473,6 +2474,8 @@ private Image findSeverityImage(DisplayModel model) { private void listener(PluginListenerDefinition definition) { switch (definition.getListenerType()) { case FILTER_CHANGED: + updateResultsTree(definition.getResutls(), true); + break; case GET_RESULTS: updateResultsTree(definition.getResutls(), false); break; @@ -2489,9 +2492,15 @@ private void listener(PluginListenerDefinition definition) { private void updateResultsTree(List results, boolean expand) { sync.asyncExec(() -> { + if (currentlyDisplayedItem == null + || currentlyDisplayedItem.getSeverity() == null + || !FilterState.isSeverityEnabled(currentlyDisplayedItem.getSeverity())) { + resultViewComposite.setVisible(false); + attackVectorCompositePanel.setVisible(false); + } + Object[] expanded = resultsTree.getExpandedElements(); rootModel.children.clear(); rootModel.children.addAll(results); - Object[] expanded = resultsTree.getExpandedElements(); resultsTree.refresh(); if (expand) { Set expandedDMNames = new HashSet<>(); From 72be7a1a6ad5e35b226a61244c889dc09f75f376 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Mon, 20 Apr 2026 10:48:41 +0530 Subject: [PATCH 4/6] Fix: Truncate long custom state names in filter menu (AST-137779) (#246) * Fix AST-137779: Truncate long custom state names in filter menu and triage combo Custom states with very long names caused the state filter dropdown menu to expand across the entire screen. Fix truncates display text to 50 chars (with trailing "...") in both the state filter MenuItem and the triage state ComboViewer LabelProvider. The full state name is still used internally for filtering and triage submission. Co-Authored-By: Claude Sonnet 4.6 (1M context) * Fix AST-137779: Guard against null getResults() in cxProjectMatchesWorkspaceProject Results.getResults() can return null when no results have been loaded yet (e.g. fresh IDE session before any scan is imported). The prior check only guarded against a null Results object, causing an NPE on the first click of the Start Scan button and preventing scans from running. Co-Authored-By: Claude Sonnet 4.6 (1M context) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- .../src/com/checkmarx/eclipse/views/CheckmarxView.java | 7 +++++++ .../eclipse/views/actions/ActionFilterStatePreference.java | 6 +++++- .../checkmarx/eclipse/views/actions/ActionStartScan.java | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java index b28a751..ec897c1 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java @@ -627,6 +627,13 @@ private void createResultViewPanel(Composite resultsComposite) { combo_1.setLayoutData(gd_combo_1); triageStateComboViewer = new ComboViewer(triageView, SWT.READ_ONLY); + triageStateComboViewer.setLabelProvider(new LabelProvider() { + @Override + public String getText(Object element) { + String s = element instanceof String ? (String) element : super.getText(element); + return s.length() > 50 ? s.substring(0, 47) + "..." : s; + } + }); Combo combo_2 = triageStateComboViewer.getCombo(); combo_2.setEnabled(true); combo_2.setData(PluginConstants.DATA_ID_KEY, PluginConstants.TRIAGE_STATE_COMBO_ID); diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java index f67d689..ecc6bbc 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java @@ -89,7 +89,7 @@ public Menu getMenu(final Control parent) { for (String customState : customStates) { MenuItem item = new MenuItem(menu, SWT.CHECK); - item.setText(customState); + item.setText(truncate(customState)); item.setSelection(FilterState.isCustomStateSelected(customState)); item.addSelectionListener(new SelectionAdapter() { @Override @@ -127,4 +127,8 @@ public void widgetSelected(SelectionEvent e) { public Menu getMenu(final Menu parent) { return null; } + + private static String truncate(String text) { + return text.length() > 50 ? text.substring(0, 47) + "..." : text; + } } \ No newline at end of file diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java index 43a5cb9..972a5d6 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java @@ -220,7 +220,7 @@ private String getCurrentGitBranch() { */ private boolean cxProjectMatchesWorkspaceProject() { Results results = DataProvider.getInstance().getCurrentResults(); - boolean noResultsInScan = results == null || results.getResults().isEmpty(); + boolean noResultsInScan = results == null || results.getResults() == null || results.getResults().isEmpty(); boolean noFilesInWorkspace = ResourcesPlugin.getWorkspace().getRoot().getProjects().length == 0; if (noResultsInScan || noFilesInWorkspace) { From d30b7f0fb1194548290a80f5abc6822ecf932131 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Thu, 14 May 2026 11:38:11 +0530 Subject: [PATCH 5/6] Toolyip custom state --- .claude/settings.local.json | 9 ++++ .../eclipse/views/CheckmarxView.java | 12 +++++ .../actions/ActionFilterStatePreference.java | 52 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..88a95af --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(git log *)", + "Bash(git pull *)", + "Bash(git stash *)" + ] + } +} diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java index ec897c1..6458798 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java @@ -41,6 +41,8 @@ import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; @@ -640,6 +642,16 @@ public String getText(Object element) { GridData gd_combo_2 = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); // gd_combo_2.widthHint = 180; combo_2.setLayoutData(gd_combo_2); + combo_2.addMouseTrackListener(new MouseTrackAdapter() { + @Override + public void mouseHover(MouseEvent e) { + IStructuredSelection sel = (IStructuredSelection) triageStateComboViewer.getSelection(); + if (!sel.isEmpty()) { + String fullName = (String) sel.getFirstElement(); + combo_2.setToolTipText(fullName.length() > 50 ? fullName : ""); + } + } + }); triageButton = new Button(triageView, SWT.FLAT | SWT.CENTER); triageButton.setData(PluginConstants.DATA_ID_KEY, PluginConstants.TRIAGE_BUTTON_ID); diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java index ecc6bbc..4482e6f 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionFilterStatePreference.java @@ -5,16 +5,21 @@ import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuCreator; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MenuAdapter; +import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.ToolItem; +import org.eclipse.swt.widgets.ToolTip; import com.checkmarx.eclipse.Activator; import com.checkmarx.eclipse.enums.ActionName; @@ -27,6 +32,9 @@ class ActionFilterStatePreference extends Action implements IMenuCreator { private Menu menu; + private ToolTip activeTip; + private Listener armFilter; + private Runnable tipTimer; private static final String ACTION_FILTER_STATE_TOOLTIP = "State"; private static final String ACTION_FILTER_STATE_ICON_PATH = "/icons/filter_ps.png"; private EventBus pluginEventBus; @@ -75,6 +83,12 @@ public Menu getMenu(final Control parent) { menu.dispose(); } menu = new Menu(parent); + menu.addMenuListener(new MenuAdapter() { + @Override + public void menuHidden(MenuEvent e) { + disposeActiveTip(); + } + }); createMenuItem(menu, FILTER_CONFIRMED, FilterState.confirmed, State.CONFIRMED); createMenuItem(menu, FILTER_NOT_EXPLOITABLE, FilterState.notExploitable, State.NOT_EXPLOITABLE); createMenuItem(menu, FILTER_PROPOSED_NON_EXPLOITABLE, FilterState.proposedNotExploitable, @@ -91,6 +105,17 @@ public Menu getMenu(final Control parent) { MenuItem item = new MenuItem(menu, SWT.CHECK); item.setText(truncate(customState)); item.setSelection(FilterState.isCustomStateSelected(customState)); + if (customState.length() > 50) { + item.addArmListener(e -> { + disposeActiveTip(); + activeTip = new ToolTip(menu.getShell(), SWT.NONE); + activeTip.setMessage(customState); + Point loc = Display.getCurrent().getCursorLocation(); + activeTip.setLocation(loc.x + 16, loc.y + 16); + activeTip.setVisible(true); + installArmFilter(item); + }); + } item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -128,6 +153,33 @@ public Menu getMenu(final Menu parent) { return null; } + private void installArmFilter(MenuItem armedItem) { + Display d = Display.getCurrent(); + if (armFilter != null) { + d.removeFilter(SWT.Arm, armFilter); + } + armFilter = event -> { if (event.widget != armedItem) disposeActiveTip(); }; + d.addFilter(SWT.Arm, armFilter); + tipTimer = this::disposeActiveTip; + d.timerExec(1800, tipTimer); + } + + private void disposeActiveTip() { + Display d = Display.getCurrent(); + if (armFilter != null) { + d.removeFilter(SWT.Arm, armFilter); + armFilter = null; + } + if (tipTimer != null) { + d.timerExec(-1, tipTimer); + tipTimer = null; + } + if (activeTip != null && !activeTip.isDisposed()) { + activeTip.dispose(); + } + activeTip = null; + } + private static String truncate(String text) { return text.length() > 50 ? text.substring(0, 47) + "..." : text; } From b02350996e2a622afc97c682529e9922d954ab4a Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Thu, 14 May 2026 15:10:15 +0530 Subject: [PATCH 6/6] Parity and project combobox --- .../eclipse/plugin/tests/ui/BaseUITest.java | 2 +- checkmarx-ast-eclipse-plugin/plugin.xml | 4 +++ .../eclipse/properties/PreferencesPage.java | 11 ++++++- .../eclipse/startup/PluginStartup.java | 31 +++++++++++++++++++ .../eclipse/utils/PluginConstants.java | 2 ++ .../eclipse/views/CheckmarxView.java | 22 +++++++++++-- .../checkmarx/eclipse/views/DataProvider.java | 20 ++++++++++-- .../eclipse/views/filters/FilterState.java | 8 ++--- 8 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/startup/PluginStartup.java diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java index 2211c71..175febc 100644 --- a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java +++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java @@ -26,7 +26,7 @@ public abstract class BaseUITest { - private static final String INFO_SUCCESSFUL_CONNECTION = "Successfully authenticated to Checkmarx One server!"; + private static final String INFO_SUCCESSFUL_CONNECTION = "You are connected to Checkmarx One"; protected static final String ASSERT_FILTER_ACTIONS_IN_TOOLBAR = "All filter actions must be in the tool bar"; diff --git a/checkmarx-ast-eclipse-plugin/plugin.xml b/checkmarx-ast-eclipse-plugin/plugin.xml index 362a4c3..e0f787b 100644 --- a/checkmarx-ast-eclipse-plugin/plugin.xml +++ b/checkmarx-ast-eclipse-plugin/plugin.xml @@ -39,4 +39,8 @@ + + + + diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java index 49cb12d..3c5af09 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java @@ -137,7 +137,7 @@ public void widgetSelected(SelectionEvent e) { return t.getMessage(); } }).thenAccept((result) -> Display.getDefault().syncExec(() -> { - connectionLabel.setText(result); + connectionLabel.setText(mapAuthResult(result)); getFieldEditorParent().layout(); connectionButton.setEnabled(true); })); @@ -145,6 +145,15 @@ public void widgetSelected(SelectionEvent e) { }); } + + + private static String mapAuthResult(String result) { + if (result != null && result.contains(PluginConstants.AUTH_SUCCESS_PATTERN)) { + return PluginConstants.AUTH_SUCCESS_DISPLAY; + } + return result; + } + private FieldEditor space() { return new LabelFieldEditor("", getFieldEditorParent()); } diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/startup/PluginStartup.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/startup/PluginStartup.java new file mode 100644 index 0000000..e520f99 --- /dev/null +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/startup/PluginStartup.java @@ -0,0 +1,31 @@ +package com.checkmarx.eclipse.startup; + +import org.eclipse.ui.IStartup; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +import com.checkmarx.eclipse.utils.CxLogger; + +public class PluginStartup implements IStartup { + + private static final String VIEW_ID = "com.checkmarx.eclipse.views.CheckmarxView"; + + @Override + public void earlyStartup() { + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { + try { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window != null) { + IWorkbenchPage page = window.getActivePage(); + if (page != null && page.findView(VIEW_ID) == null) { + page.showView(VIEW_ID); + } + } + } catch (PartInitException e) { + CxLogger.error("Failed to open Checkmarx One view on startup: " + e.getMessage(), e); + } + }); + } +} diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/utils/PluginConstants.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/utils/PluginConstants.java index ad48cd2..524b113 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/utils/PluginConstants.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/utils/PluginConstants.java @@ -49,6 +49,8 @@ public class PluginConstants { public static final String INFO_CHANGE_SCAN_EVENT_NOT_TRIGGERED = "Change scan id event not triggered. Request already running: %s. Scan id results already retrieved: %s"; public static final String INFO_CHANGE_BRANCH_EVENT_NOT_TRIGGERED = "Change branch event not triggered. Branch already selected"; public static final String INFO_CHANGE_PROJECT_EVENT_NOT_TRIGGERED = "Change project event not triggered. Project already selected"; + public static final String AUTH_SUCCESS_PATTERN = "Successfully authenticated"; + public static final String AUTH_SUCCESS_DISPLAY = "You are connected to Checkmarx One"; /******************************** TREE MESSAGES ********************************/ public static final String TREE_INVALID_SCAN_ID_FORMAT = "Invalid scan id format."; diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java index 43c16a4..8c2b11d 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java @@ -1264,13 +1264,31 @@ protected IStatus run(IProgressMonitor arg0) { List projectList = getProjects(); if (projectList.isEmpty()) return null; - String projectName = getProjectFromId(projectList, projectId); + + // Fetch the project directly by ID — the full list may not contain it (e.g. pagination limits) + Project fetchedProject = DataProvider.getInstance().getProjectById(projectId); + + // Determine project name: prefer the directly-fetched result, fall back to list lookup + String projectName = (fetchedProject != null) + ? fetchedProject.getName() + : getProjectFromId(projectList, projectId); + + // If the project was not already in the list, prepend it so it's visible in the dropdown + if (fetchedProject != null && projectList.stream().noneMatch(p -> p.getId().equals(projectId))) { + projectList = new ArrayList<>(projectList); + projectList.add(0, fetchedProject); + } + final List finalProjectList = projectList; + currentProjectId = projectId; GlobalSettings.storeInPreferences(GlobalSettings.PARAM_PROJECT_ID, currentProjectId); sync.asyncExec(() -> { - projectComboViewer.setInput(projectList); + currentProjects = finalProjectList; + storeCurrentProjects = finalProjectList; + projectComboViewer.setInput(finalProjectList); PluginUtils.setTextForComboViewer(projectComboViewer, projectName); + PluginUtils.enableComboViewer(projectComboViewer, true); setSelectionForBranchComboViewer(scan.getBranch(), projectId); setSelectionForScanIdComboViewer(scan.getId(), scan.getBranch()); updateStartScanButton(true); diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/DataProvider.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/DataProvider.java index d022932..efe9f5e 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/DataProvider.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/DataProvider.java @@ -112,11 +112,27 @@ public List getProjects() throws Exception { return projectList; } + /** + * Fetch a single project directly by its ID using the project show command. + * Returns null if the project cannot be retrieved. + */ + public Project getProjectById(String projectId) { + try { + CxWrapper cxWrapper = getWrapper(); + if (cxWrapper != null && projectId != null && !projectId.isEmpty()) { + return cxWrapper.projectShow(UUID.fromString(projectId)); + } + } catch (Exception e) { + CxLogger.error(String.format(PluginConstants.ERROR_GETTING_PROJECTS, e.getMessage()), e); + } + return null; + } + /** * Get One projects filtered by name - * + * * @return - * @throws Exception + * @throws Exception */ public List getProjects(String projectName) throws Exception { List projectList = new ArrayList(); diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/filters/FilterState.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/filters/FilterState.java index a3c41d0..e595711 100644 --- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/filters/FilterState.java +++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/filters/FilterState.java @@ -15,8 +15,8 @@ public class FilterState { public static boolean critical = true; public static boolean high = true; public static boolean medium = true; - public static boolean low = false; - public static boolean info = false; + public static boolean low = true; + public static boolean info = true; public static boolean groupBySeverity = true; public static boolean groupByQueryName = false; public static boolean groupByStateName = false; @@ -42,8 +42,8 @@ public static void loadFiltersFromSettings() { critical = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.CRITICAL.name(), "true")); high = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.HIGH.name(), "true")); medium = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.MEDIUM.name(), "true")); - low = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.LOW.name(), "false")); - info = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.INFO.name(), "false")); + low = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.LOW.name(), "true")); + info = Boolean.parseBoolean(GlobalSettings.getFromPreferences(Severity.INFO.name(), "true")); groupBySeverity = Boolean .parseBoolean(GlobalSettings.getFromPreferences(Severity.GROUP_BY_SEVERITY.name(), "true")); groupByQueryName = Boolean