Skip to content

Commit 5c478e9

Browse files
authored
Merge pull request #1532 from github/koesie10/split-common-components
Split CodePaths and FileCodeSnippet into multiple files
2 parents 99fe65f + 9ad28f3 commit 5c478e9

9 files changed

Lines changed: 465 additions & 424 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as React from 'react';
2+
import { ChangeEvent, SetStateAction, useCallback } from 'react';
3+
import { VSCodeDropdown, VSCodeOption } from '@vscode/webview-ui-toolkit/react';
4+
5+
import { CodeFlow } from '../../../remote-queries/shared/analysis-result';
6+
7+
const getCodeFlowName = (codeFlow: CodeFlow) => {
8+
const filePath = codeFlow.threadFlows[codeFlow.threadFlows.length - 1].fileLink.filePath;
9+
return filePath.substring(filePath.lastIndexOf('/') + 1);
10+
};
11+
12+
type CodeFlowsDropdownProps = {
13+
codeFlows: CodeFlow[];
14+
setSelectedCodeFlow: (value: SetStateAction<CodeFlow>) => void;
15+
}
16+
17+
export const CodeFlowsDropdown = ({
18+
codeFlows,
19+
setSelectedCodeFlow
20+
}: CodeFlowsDropdownProps) => {
21+
const handleChange = useCallback((e: ChangeEvent<HTMLSelectElement>) => {
22+
const selectedOption = e.target;
23+
const selectedIndex = selectedOption.value as unknown as number;
24+
setSelectedCodeFlow(codeFlows[selectedIndex]);
25+
}, [setSelectedCodeFlow, codeFlows]);
26+
27+
return (
28+
<VSCodeDropdown onChange={handleChange}>
29+
{codeFlows.map((codeFlow, index) =>
30+
<VSCodeOption
31+
key={index}
32+
value={index}
33+
>
34+
{getCodeFlowName(codeFlow)}
35+
</VSCodeOption>
36+
)}
37+
</VSCodeDropdown>
38+
);
39+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as React from 'react';
2+
3+
import { AnalysisMessage, CodeFlow, ResultSeverity } from '../../../remote-queries/shared/analysis-result';
4+
import { ThreadPath } from './ThreadPath';
5+
6+
type CodePathProps = {
7+
codeFlow: CodeFlow;
8+
message: AnalysisMessage;
9+
severity: ResultSeverity;
10+
}
11+
12+
export const CodePath = ({
13+
codeFlow,
14+
message,
15+
severity
16+
}: CodePathProps) => (
17+
<>
18+
{codeFlow.threadFlows.map((threadFlow, index) =>
19+
<ThreadPath
20+
key={index}
21+
threadFlow={threadFlow}
22+
step={index + 1}
23+
message={message}
24+
severity={severity}
25+
isSource={index === 0}
26+
isSink={index === codeFlow.threadFlows.length - 1}
27+
/>
28+
)}
29+
</>
30+
);

extensions/ql-vscode/src/view/common/CodePaths/CodePaths.tsx

Lines changed: 4 additions & 226 deletions
Original file line numberDiff line numberDiff line change
@@ -1,239 +1,17 @@
11
import * as React from 'react';
2-
import { ChangeEvent, SetStateAction, useCallback, useRef, useState } from 'react';
2+
import { useRef, useState } from 'react';
33
import styled from 'styled-components';
4-
import { VSCodeDropdown, VSCodeLink, VSCodeOption, VSCodeTag } from '@vscode/webview-ui-toolkit/react';
4+
import { VSCodeLink } from '@vscode/webview-ui-toolkit/react';
55

66
import { Overlay } from '@primer/react';
77

8-
import { CodeFlow, AnalysisMessage, ResultSeverity, ThreadFlow } from '../../../remote-queries/shared/analysis-result';
9-
import { SectionTitle } from '../SectionTitle';
10-
import { VerticalSpace } from '../VerticalSpace';
11-
import { FileCodeSnippet } from '../FileCodeSnippet';
12-
13-
const StyledCloseButton = styled.button`
14-
position: absolute;
15-
top: 1em;
16-
right: 4em;
17-
background-color: var(--vscode-editor-background);
18-
color: var(--vscode-editor-foreground);
19-
border: none;
20-
cursor: pointer;
21-
22-
&:focus-visible {
23-
outline: none
24-
}
25-
`;
26-
27-
const OverlayContainer = styled.div`
28-
height: 100%;
29-
width: 100%;
30-
padding: 2em;
31-
position: fixed;
32-
top: 0;
33-
left: 0;
34-
background-color: var(--vscode-editor-background);
35-
color: var(--vscode-editor-foreground);
36-
overflow-y: scroll;
37-
`;
38-
39-
const CloseButton = ({ onClick }: { onClick: () => void }) => (
40-
<StyledCloseButton onClick={onClick} tabIndex={-1}>
41-
<span className="codicon codicon-chrome-close" />
42-
</StyledCloseButton>
43-
);
44-
45-
const PathsContainer = styled.div`
46-
display: flex;
47-
justify-content: center;
48-
align-items: center;
49-
`;
50-
51-
const PathDetailsContainer = styled.div`
52-
padding: 0;
53-
border: 0;
54-
`;
55-
56-
const PathDropdownContainer = styled.div`
57-
flex-grow: 1;
58-
padding: 0 0 0 0.2em;
59-
border: none;
60-
`;
61-
62-
const Container = styled.div`
63-
max-width: 55em;
64-
margin-bottom: 1.5em;
65-
`;
66-
67-
const HeaderContainer = styled.div`
68-
display: flex;
69-
justify-content: center;
70-
align-items: center;
71-
margin-bottom: 1em;
72-
`;
73-
74-
const TitleContainer = styled.div`
75-
flex-grow: 1;
76-
padding: 0;
77-
border: none;
78-
`;
79-
80-
const TagContainer = styled.div`
81-
padding: 0;
82-
border: none;
83-
`;
8+
import { AnalysisMessage, CodeFlow, ResultSeverity } from '../../../remote-queries/shared/analysis-result';
9+
import { CodePathsOverlay } from './CodePathsOverlay';
8410

8511
const ShowPathsLink = styled(VSCodeLink)`
8612
cursor: pointer;
8713
`;
8814

89-
type ThreadPathProps = {
90-
threadFlow: ThreadFlow;
91-
step: number;
92-
message: AnalysisMessage;
93-
severity: ResultSeverity;
94-
isSource?: boolean;
95-
isSink?: boolean;
96-
}
97-
98-
const ThreadPath = ({
99-
threadFlow,
100-
step,
101-
message,
102-
severity,
103-
isSource,
104-
isSink,
105-
}: ThreadPathProps) => (
106-
<Container>
107-
<HeaderContainer>
108-
<TitleContainer>
109-
<SectionTitle>Step {step}</SectionTitle>
110-
</TitleContainer>
111-
{isSource &&
112-
<TagContainer>
113-
<VSCodeTag>Source</VSCodeTag>
114-
</TagContainer>
115-
}
116-
{isSink &&
117-
<TagContainer>
118-
<VSCodeTag>Sink</VSCodeTag>
119-
</TagContainer>
120-
}
121-
</HeaderContainer>
122-
123-
<FileCodeSnippet
124-
fileLink={threadFlow.fileLink}
125-
codeSnippet={threadFlow.codeSnippet}
126-
highlightedRegion={threadFlow.highlightedRegion}
127-
severity={severity}
128-
message={isSink ? message : threadFlow.message}
129-
/>
130-
</Container>
131-
);
132-
133-
type CodePathProps = {
134-
codeFlow: CodeFlow;
135-
message: AnalysisMessage;
136-
severity: ResultSeverity;
137-
}
138-
139-
const CodePath = ({
140-
codeFlow,
141-
message,
142-
severity
143-
}: CodePathProps) => (
144-
<>
145-
{codeFlow.threadFlows.map((threadFlow, index) =>
146-
<ThreadPath
147-
key={index}
148-
threadFlow={threadFlow}
149-
step={index + 1}
150-
message={message}
151-
severity={severity}
152-
isSource={index === 0}
153-
isSink={index === codeFlow.threadFlows.length - 1}
154-
/>
155-
)}
156-
</>
157-
);
158-
159-
const getCodeFlowName = (codeFlow: CodeFlow) => {
160-
const filePath = codeFlow.threadFlows[codeFlow.threadFlows.length - 1].fileLink.filePath;
161-
return filePath.substring(filePath.lastIndexOf('/') + 1);
162-
};
163-
164-
type CodeFlowsDropdownProps = {
165-
codeFlows: CodeFlow[];
166-
setSelectedCodeFlow: (value: SetStateAction<CodeFlow>) => void;
167-
}
168-
169-
const CodeFlowsDropdown = ({
170-
codeFlows,
171-
setSelectedCodeFlow
172-
}: CodeFlowsDropdownProps) => {
173-
const handleChange = useCallback((e: ChangeEvent<HTMLSelectElement>) => {
174-
const selectedOption = e.target;
175-
const selectedIndex = selectedOption.value as unknown as number;
176-
setSelectedCodeFlow(codeFlows[selectedIndex]);
177-
}, [setSelectedCodeFlow, codeFlows]);
178-
179-
return (
180-
<VSCodeDropdown onChange={handleChange}>
181-
{codeFlows.map((codeFlow, index) =>
182-
<VSCodeOption
183-
key={index}
184-
value={index}
185-
>
186-
{getCodeFlowName(codeFlow)}
187-
</VSCodeOption>
188-
)}
189-
</VSCodeDropdown>
190-
);
191-
};
192-
193-
type CodePathsOverlayProps = {
194-
codeFlows: CodeFlow[];
195-
ruleDescription: string;
196-
message: AnalysisMessage;
197-
severity: ResultSeverity;
198-
onClose: () => void;
199-
}
200-
201-
const CodePathsOverlay = ({
202-
codeFlows,
203-
ruleDescription,
204-
message,
205-
severity,
206-
onClose,
207-
}: CodePathsOverlayProps) => {
208-
const [selectedCodeFlow, setSelectedCodeFlow] = useState(codeFlows[0]);
209-
210-
return (
211-
<OverlayContainer>
212-
<CloseButton onClick={onClose} />
213-
214-
<SectionTitle>{ruleDescription}</SectionTitle>
215-
<VerticalSpace size={2} />
216-
217-
<PathsContainer>
218-
<PathDetailsContainer>
219-
{codeFlows.length} paths available: {selectedCodeFlow.threadFlows.length} steps in
220-
</PathDetailsContainer>
221-
<PathDropdownContainer>
222-
<CodeFlowsDropdown codeFlows={codeFlows} setSelectedCodeFlow={setSelectedCodeFlow} />
223-
</PathDropdownContainer>
224-
</PathsContainer>
225-
226-
<VerticalSpace size={2} />
227-
<CodePath
228-
codeFlow={selectedCodeFlow}
229-
severity={severity}
230-
message={message}
231-
/>
232-
<VerticalSpace size={3} />
233-
</OverlayContainer>
234-
);
235-
};
236-
23715
type Props = {
23816
codeFlows: CodeFlow[],
23917
ruleDescription: string,

0 commit comments

Comments
 (0)