Diff-View
1. Overview¶
The Diff View is a feature integrated into the SecAI SonarQube plugin that provides a side-by-side comparison between a piece of code with a known vulnerability and the secure code snippet generated by the AI Fix feature. Its primary purpose is to offer developers a clear and immediate visualization of the changes proposed by the AI, facilitating a quick review and validation process.
2. Technical Implementation¶
The feature is implemented on the frontend using React and Redux for state management. It involves a main view component that orchestrates the display of tabs, a new dedicated component for rendering the diff, and the Redux store for managing the state of the code snippets.
2.1. Core Components¶
DiffView.js¶
This is a new, specialized component responsible for rendering the code comparison.
- Purpose: To display a side-by-side diff of the original (vulnerable) code and the AI-generated (fixed) code.
- Dependency: It utilizes the react-diff-viewer-continued library to handle the complexities of diff rendering, including line-by-line highlighting of additions and deletions.
- Props:
- oldCode: A string containing the original source code snippet.
- newCode: A string containing the AI-generated secure code snippet.
File: main/js/sec_ai/components/Description/DiffView.js
import React from 'react';
import ReactDiffViewer from 'react-diff-viewer-continued';
import 'react-diff-viewer-continued/dist/style.css';
const DiffView = ({ oldCode, newCode }) => {
if (!oldCode || !newCode) {
return <p>Not enough data to display the diff.</p>;
}
return (
<ReactDiffViewer
oldValue={oldCode}
newValue={newCode}
splitView={true}
leftTitle="Original Code"
rightTitle="AI Generated Fix"
/>
);
};
export default DiffView;
DetailedFix.js¶
This component serves as the main container for displaying issue details and orchestrates the visibility of the "Diff View" tab.
- Dynamic Tab Management: The list of navigation tabs (navs) is dynamically generated using a React.useMemo hook. The "Diff View" tab is conditionally added to this list only when an AI solution is present in the Redux store.
- Automatic Tab Switching: A useEffect hook monitors the aiSolution state. When a new solution is generated and populated in the store, this hook automatically sets "Diff View" as the active tab, bringing the changes to the user's immediate attention.
- State Propagation: It retrieves the sourceSnippet (original code) and aiSolution (which contains the new code) from the Redux store and passes them as props to the DiffView component.
File: main/js/sec_ai/components/Navigations/DetailedFix.js
// ... (imports)
function DetailedFix({ jumpTarget, clearJumpTarget }) {
// ... (state and selectors)
const sourceSnippet = useSelector(selectSourceCode);
const aiSolution = useSelector(selectAiSolution);
const [selectedTab, setSelectedTab] = useState('Root Cause');
const navs = React.useMemo(() => {
// ... (logic to build base tab list)
if (aiSolution && aiSolution.Final_Secure_Code_Snippet) {
list.push('Diff View');
}
return list;
}, [selectedIssue, aiSolution]);
useEffect(() => {
if (aiSolution && aiSolution.Final_Secure_Code_Snippet) {
setSelectedTab('Diff View');
}
}, [aiSolution]);
// ... (render logic)
{selectedTab === "Diff View" && (
<DiffView
oldCode={sourceSnippet}
newCode={aiSolution?.Final_Secure_Code_Snippet}
/>
)}
// ...
}
2.2. State Management (Redux)¶
The issuesReducer.js manages the state required for the Diff View to function.
- aiSolution State: When a user generates an AI fix in the
AiFix.jscomponent, the resulting JSON object, which includes theFinal_Secure_Code_Snippet, is dispatched and stored in theaiSolutionslice of the Redux state. - sourceCode State: The original code snippet associated with a selected issue is stored in the
sourceCodeslice. This is populated when a user clicks on an issue from the list. - Selectors: The
selectAiSolutionandselectSourceCodeselectors are used byDetailedFix.jsto retrieve the necessary data from the store.
3. User Flow¶
- A user selects a vulnerability from the issue list in the main view.
- The application fetches the issue details, including the original code snippet (
sourceSnippet), and stores it in the Redux store. - The user navigates to the "AI Fix" tab and clicks the "Generate the fix" button.
- The
AiFix.jscomponent sends a request to the backend. Upon receiving a successful response, it dispatches thesetAiSolutionaction to update the Redux store with the AI-generated fix. - The
useEffecthook inDetailedFix.jsdetects the change in theaiSolutionstate. - The component automatically switches the active tab to "Diff View".
- The
DiffViewcomponent renders, receiving the original code fromsourceSnippetand the new code fromaiSolution.Final_Secure_Code_Snippet, displaying them side-by-side.
4. Dependencies¶
- react-diff-viewer-continued: A React component for displaying text diffs. This is a new dependency added to support this feature.