Skip to content

Commit 26b579e

Browse files
committed
Rewrite clippy reducer with RTK
1 parent bdcd536 commit 26b579e

File tree

6 files changed

+58
-61
lines changed

6 files changed

+58
-61
lines changed

ui/frontend/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ module.exports = {
7474
'reducers/featureFlags.ts',
7575
'reducers/globalConfiguration.ts',
7676
'reducers/output/assembly.ts',
77+
'reducers/output/clippy.ts',
7778
'reducers/output/execute.ts',
7879
'reducers/output/format.ts',
7980
'reducers/output/gist.ts',

ui/frontend/.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ node_modules
2525
!reducers/featureFlags.ts
2626
!reducers/globalConfiguration.ts
2727
!reducers/output/assembly.ts
28+
!reducers/output/clippy.ts
2829
!reducers/output/execute.ts
2930
!reducers/output/format.ts
3031
!reducers/output/gist.ts

ui/frontend/ToolsMenu.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as selectors from './selectors';
99
import * as actions from './actions';
1010
import { useAppDispatch } from './configureStore';
1111
import { performFormat } from './reducers/output/format';
12+
import { performClippy } from './reducers/output/clippy';
1213

1314
interface ToolsMenuProps {
1415
close: () => void;
@@ -26,7 +27,7 @@ const ToolsMenu: React.FC<ToolsMenuProps> = props => {
2627

2728
const dispatch = useAppDispatch();
2829
const clippy = useCallback(() => {
29-
dispatch(actions.performClippy());
30+
dispatch(performClippy());
3031
props.close();
3132
}, [dispatch, props]);
3233
const miri = useCallback(() => {

ui/frontend/actions.ts

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { ThunkAction as ReduxThunkAction, AnyAction } from '@reduxjs/toolkit';
33

44
import {
55
codeSelector,
6-
clippyRequestSelector,
76
getCrateType,
87
runAsTest,
98
wasmLikelyToWork,
@@ -84,9 +83,6 @@ export enum ActionType {
8483
EnableFeatureGate = 'ENABLE_FEATURE_GATE',
8584
GotoPosition = 'GOTO_POSITION',
8685
SelectText = 'SELECT_TEXT',
87-
RequestClippy = 'REQUEST_CLIPPY',
88-
ClippySucceeded = 'CLIPPY_SUCCEEDED',
89-
ClippyFailed = 'CLIPPY_FAILED',
9086
RequestMiri = 'REQUEST_MIRI',
9187
MiriSucceeded = 'MIRI_SUCCEEDED',
9288
MiriFailed = 'MIRI_FAILED',
@@ -346,42 +342,6 @@ interface GeneralSuccess {
346342
stderr: string;
347343
}
348344

349-
const requestClippy = () =>
350-
createAction(ActionType.RequestClippy);
351-
352-
interface ClippyRequestBody {
353-
code: string;
354-
edition: string;
355-
crateType: string;
356-
}
357-
358-
interface ClippyResponseBody {
359-
success: boolean;
360-
stdout: string;
361-
stderr: string;
362-
}
363-
364-
type ClippySuccess = GeneralSuccess;
365-
366-
const receiveClippySuccess = ({ stdout, stderr }: ClippySuccess) =>
367-
createAction(ActionType.ClippySucceeded, { stdout, stderr });
368-
369-
const receiveClippyFailure = ({ error }: GenericApiFailure) =>
370-
createAction(ActionType.ClippyFailed, { error });
371-
372-
export function performClippy(): ThunkAction {
373-
// TODO: Check a cache
374-
return function(dispatch, getState) {
375-
dispatch(requestClippy());
376-
377-
const body: ClippyRequestBody = clippyRequestSelector(getState());
378-
379-
return jsonPost<ClippyResponseBody>(routes.clippy, body)
380-
.then(json => dispatch(receiveClippySuccess(json)))
381-
.catch(json => dispatch(receiveClippyFailure(json)));
382-
};
383-
}
384-
385345
const requestMiri = () =>
386346
createAction(ActionType.RequestMiri);
387347

@@ -597,9 +557,6 @@ export type Action =
597557
| ReturnType<typeof enableFeatureGate>
598558
| ReturnType<typeof gotoPosition>
599559
| ReturnType<typeof selectText>
600-
| ReturnType<typeof requestClippy>
601-
| ReturnType<typeof receiveClippySuccess>
602-
| ReturnType<typeof receiveClippyFailure>
603560
| ReturnType<typeof requestMiri>
604561
| ReturnType<typeof receiveMiriSuccess>
605562
| ReturnType<typeof receiveMiriFailure>

ui/frontend/reducers/output/clippy.ts

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { Action, ActionType } from '../../actions';
2-
import { finish, start } from './sharedStateManagement';
1+
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
2+
import * as z from 'zod';
33

4-
const DEFAULT: State = {
4+
import { adaptFetchError, jsonPost, routes } from '../../actions';
5+
import { clippyRequestSelector } from '../../selectors';
6+
import RootState from '../../state';
7+
8+
const sliceName = 'output/clippy';
9+
10+
const initialState: State = {
511
requestsInProgress: 0,
612
};
713

@@ -12,17 +18,47 @@ interface State {
1218
error?: string;
1319
}
1420

15-
export default function clippy(state = DEFAULT, action: Action) {
16-
switch (action.type) {
17-
case ActionType.RequestClippy:
18-
return start(DEFAULT, state);
19-
case ActionType.ClippySucceeded: {
20-
const { stdout = '', stderr = '' } = action;
21-
return finish(state, { stdout, stderr });
22-
}
23-
case ActionType.ClippyFailed:
24-
return finish(state, { error: action.error });
25-
default:
26-
return state;
27-
}
21+
interface ClippyRequestBody {
22+
code: string;
23+
edition: string;
24+
crateType: string;
2825
}
26+
27+
const ClippyResponseBody = z.object({
28+
success: z.boolean(),
29+
stdout: z.string(),
30+
stderr: z.string(),
31+
});
32+
33+
type ClippyResponseBody = z.infer<typeof ClippyResponseBody>;
34+
35+
export const performClippy = createAsyncThunk<ClippyResponseBody, void, { state: RootState }>(
36+
sliceName,
37+
async (_arg: void, { getState }) => {
38+
const body: ClippyRequestBody = clippyRequestSelector(getState());
39+
40+
const d = await adaptFetchError(() => jsonPost(routes.clippy, body));
41+
return ClippyResponseBody.parseAsync(d);
42+
},
43+
);
44+
45+
const slice = createSlice({
46+
name: sliceName,
47+
initialState,
48+
reducers: {},
49+
extraReducers: (builder) => {
50+
builder
51+
.addCase(performClippy.pending, (state) => {
52+
state.requestsInProgress += 1;
53+
})
54+
.addCase(performClippy.fulfilled, (state, action) => {
55+
state.requestsInProgress -= 1;
56+
Object.assign(state, action.payload);
57+
})
58+
.addCase(performClippy.rejected, (state) => {
59+
state.requestsInProgress -= 1;
60+
});
61+
},
62+
});
63+
64+
export default slice.reducer;

ui/frontend/reducers/output/meta.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Draft } from 'immer';
44
import { ActionType } from '../../actions';
55
import { Focus } from '../../types';
66
import { performCompileAssembly } from './assembly';
7+
import { performClippy } from './clippy';
78
import { performExecute, wsExecuteRequest } from './execute';
89
import { performFormat } from './format';
910
import { performGistLoad, performGistSave } from './gist';
@@ -35,7 +36,7 @@ const slice = createSlice({
3536
},
3637
extraReducers: (builder) => {
3738
builder
38-
.addCase(ActionType.RequestClippy, (state) => {
39+
.addCase(performClippy.pending, (state) => {
3940
state.focus = Focus.Clippy;
4041
})
4142

0 commit comments

Comments
 (0)