From 644dae9093cb13b404b273e13db21772287bd2c8 Mon Sep 17 00:00:00 2001 From: Aniket Shinde Date: Mon, 20 Apr 2026 10:47:29 +0530 Subject: [PATCH 1/3] 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 740e12a6..3df473f4 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 9484950e..202baa99 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 2/3] 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 43c16a47..b28a7511 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 3/3] 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 b28a7511..ec897c11 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 f67d6899..ecc6bbcb 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 43a5cb9c..972a5d68 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) {