Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite output reducers with RTK #1009

Merged
merged 4 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ui/frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ module.exports = {
'editor/AceEditor.tsx',
'editor/SimpleEditor.tsx',
'reducers/client.ts',
'reducers/crates.ts',
'reducers/featureFlags.ts',
'reducers/globalConfiguration.ts',
'reducers/output/assembly.ts',
Expand All @@ -80,8 +81,10 @@ module.exports = {
'reducers/output/gist.ts',
'reducers/output/hir.ts',
'reducers/output/llvmIr.ts',
'reducers/output/macroExpansion.ts',
'reducers/output/meta.ts',
'reducers/output/mir.ts',
'reducers/output/miri.ts',
'reducers/output/wasm.ts',
'reducers/versions.ts',
'reducers/websocket.ts',
Expand Down
3 changes: 3 additions & 0 deletions ui/frontend/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ node_modules
!editor/AceEditor.tsx
!editor/SimpleEditor.tsx
!reducers/client.ts
!reducers/crates.ts
!reducers/featureFlags.ts
!reducers/globalConfiguration.ts
!reducers/output/assembly.ts
Expand All @@ -31,8 +32,10 @@ node_modules
!reducers/output/gist.ts
!reducers/output/hir.ts
!reducers/output/llvmIr.ts
!reducers/output/macroExpansion.ts
!reducers/output/meta.ts
!reducers/output/mir.ts
!reducers/output/miri.ts
!reducers/output/wasm.ts
!reducers/versions.ts
!reducers/websocket.ts
Expand Down
7 changes: 4 additions & 3 deletions ui/frontend/ToolsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import MenuGroup from './MenuGroup';
import MenuAside from './MenuAside';

import * as selectors from './selectors';
import * as actions from './actions';
import { useAppDispatch } from './configureStore';
import { performFormat } from './reducers/output/format';
import { performClippy } from './reducers/output/clippy';
import { performMiri } from './reducers/output/miri';
import { performMacroExpansion } from './reducers/output/macroExpansion';

interface ToolsMenuProps {
close: () => void;
Expand All @@ -31,15 +32,15 @@ const ToolsMenu: React.FC<ToolsMenuProps> = props => {
props.close();
}, [dispatch, props]);
const miri = useCallback(() => {
dispatch(actions.performMiri());
dispatch(performMiri());
props.close();
}, [dispatch, props]);
const format = useCallback(() => {
dispatch(performFormat());
props.close();
}, [dispatch, props]);
const expandMacros = useCallback(() => {
dispatch(actions.performMacroExpansion());
dispatch(performMacroExpansion());
props.close();
}, [dispatch, props]);

Expand Down
123 changes: 0 additions & 123 deletions ui/frontend/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import fetch from 'isomorphic-fetch';
import { ThunkAction as ReduxThunkAction, AnyAction } from '@reduxjs/toolkit';

import {
codeSelector,
getCrateType,
runAsTest,
wasmLikelyToWork,
Expand All @@ -26,7 +25,6 @@ import {
ProcessAssembly,
Position,
makePosition,
Crate,
} from './types';

import { performCommonExecute, wsExecuteRequest } from './reducers/output/execute';
Expand Down Expand Up @@ -83,14 +81,6 @@ export enum ActionType {
EnableFeatureGate = 'ENABLE_FEATURE_GATE',
GotoPosition = 'GOTO_POSITION',
SelectText = 'SELECT_TEXT',
RequestMiri = 'REQUEST_MIRI',
MiriSucceeded = 'MIRI_SUCCEEDED',
MiriFailed = 'MIRI_FAILED',
RequestMacroExpansion = 'REQUEST_MACRO_EXPANSION',
MacroExpansionSucceeded = 'MACRO_EXPANSION_SUCCEEDED',
MacroExpansionFailed = 'MACRO_EXPANSION_FAILED',
RequestCratesLoad = 'REQUEST_CRATES_LOAD',
CratesLoadSucceeded = 'CRATES_LOAD_SUCCEEDED',
NotificationSeen = 'NOTIFICATION_SEEN',
BrowserWidthChanged = 'BROWSER_WIDTH_CHANGED',
}
Expand Down Expand Up @@ -258,10 +248,6 @@ const performTestOnly = (): ThunkAction => (dispatch, getState) => {
return dispatch(performCommonExecute(crateType, true));
};

interface GenericApiFailure {
error: string;
}

const performCompileToNightlyHirOnly = (): ThunkAction => dispatch => {
dispatch(changeChannel(Channel.Nightly));
dispatch(performCompileToHirOnly());
Expand Down Expand Up @@ -337,107 +323,6 @@ export const gotoPosition = (line: string | number, column: string | number) =>
export const selectText = (start: Position, end: Position) =>
createAction(ActionType.SelectText, { start, end });

interface GeneralSuccess {
stdout: string;
stderr: string;
}

const requestMiri = () =>
createAction(ActionType.RequestMiri);

interface MiriRequestBody {
code: string;
edition: string;
}

interface MiriResponseBody {
success: boolean;
stdout: string;
stderr: string;
}

type MiriSuccess = GeneralSuccess;

const receiveMiriSuccess = ({ stdout, stderr }: MiriSuccess) =>
createAction(ActionType.MiriSucceeded, { stdout, stderr });

const receiveMiriFailure = ({ error }: GenericApiFailure) =>
createAction(ActionType.MiriFailed, { error });

export function performMiri(): ThunkAction {
// TODO: Check a cache
return function(dispatch, getState) {
dispatch(requestMiri());

const state = getState();
const code = codeSelector(state);
const { configuration: {
edition,
} } = state;
const body: MiriRequestBody = { code, edition };

return jsonPost<MiriResponseBody>(routes.miri, body)
.then(json => dispatch(receiveMiriSuccess(json)))
.catch(json => dispatch(receiveMiriFailure(json)));
};
}

const requestMacroExpansion = () =>
createAction(ActionType.RequestMacroExpansion);

interface MacroExpansionRequestBody {
code: string;
edition: string;
}

interface MacroExpansionResponseBody {
success: boolean;
stdout: string;
stderr: string;
}

type MacroExpansionSuccess = GeneralSuccess;

const receiveMacroExpansionSuccess = ({ stdout, stderr }: MacroExpansionSuccess) =>
createAction(ActionType.MacroExpansionSucceeded, { stdout, stderr });

const receiveMacroExpansionFailure = ({ error }: GenericApiFailure) =>
createAction(ActionType.MacroExpansionFailed, { error });

export function performMacroExpansion(): ThunkAction {
// TODO: Check a cache
return function(dispatch, getState) {
dispatch(requestMacroExpansion());

const state = getState();
const code = codeSelector(state);
const { configuration: {
edition,
} } = state;
const body: MacroExpansionRequestBody = { code, edition };

return jsonPost<MacroExpansionResponseBody>(routes.macroExpansion, body)
.then(json => dispatch(receiveMacroExpansionSuccess(json)))
.catch(json => dispatch(receiveMacroExpansionFailure(json)));
};
}

const requestCratesLoad = () =>
createAction(ActionType.RequestCratesLoad);

const receiveCratesLoadSuccess = ({ crates }: { crates: Crate[] }) =>
createAction(ActionType.CratesLoadSucceeded, { crates });

export function performCratesLoad(): ThunkAction {
return function(dispatch) {
dispatch(requestCratesLoad());

return jsonGet(routes.meta.crates)
.then(json => dispatch(receiveCratesLoadSuccess(json)));
// TODO: Failure case
};
}

const notificationSeen = (notification: Notification) =>
createAction(ActionType.NotificationSeen, { notification });

Expand Down Expand Up @@ -557,14 +442,6 @@ export type Action =
| ReturnType<typeof enableFeatureGate>
| ReturnType<typeof gotoPosition>
| ReturnType<typeof selectText>
| ReturnType<typeof requestMiri>
| ReturnType<typeof receiveMiriSuccess>
| ReturnType<typeof receiveMiriFailure>
| ReturnType<typeof requestMacroExpansion>
| ReturnType<typeof receiveMacroExpansionSuccess>
| ReturnType<typeof receiveMacroExpansionFailure>
| ReturnType<typeof requestCratesLoad>
| ReturnType<typeof receiveCratesLoadSuccess>
| ReturnType<typeof notificationSeen>
| ReturnType<typeof browserWidthChanged>
| ReturnType<typeof wsExecuteRequest>
Expand Down
2 changes: 1 addition & 1 deletion ui/frontend/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
gotoPosition,
selectText,
addImport,
performCratesLoad,
reExecuteWithBacktrace,
browserWidthChanged,
} from './actions';
Expand All @@ -27,6 +26,7 @@ import { disableSyncChangesToStorage } from './reducers/globalConfiguration';
import Router from './Router';
import configureStore from './configureStore';
import { performVersionsLoad } from './reducers/versions';
import { performCratesLoad } from './reducers/crates';

const store = configureStore(window);

Expand Down
39 changes: 29 additions & 10 deletions ui/frontend/reducers/crates.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { sortBy } from 'lodash-es';
import * as z from 'zod';

import { Action, ActionType } from '../actions';
import { adaptFetchError, jsonGet, routes } from '../actions';
import { Crate } from '../types';

const DEFAULT: State = [];
const sliceName = 'crates';

const initialState: State = [];

export type State = Crate[];

export default function crates(state = DEFAULT, action: Action) {
switch (action.type) {
case ActionType.CratesLoadSucceeded:
return sortBy(action.crates, c => c.name);
default:
return state;
}
}
const CratesResponse = z.object({
crates: Crate.array(),
});
type CratesResponse = z.infer<typeof CratesResponse>;

export const performCratesLoad = createAsyncThunk(sliceName, async () => {
const d = await adaptFetchError(() => jsonGet(routes.meta.crates));
const crates = await CratesResponse.parseAsync(d);
return sortBy(crates.crates, (c) => c.name);
});

const slice = createSlice({
name: sliceName,
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(performCratesLoad.fulfilled, (_state, action) => {
return action.payload;
});
},
});

export default slice.reducer;
4 changes: 2 additions & 2 deletions ui/frontend/reducers/output/gist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import { jsonGet, jsonPost, routes } from '../../actions';
import { baseUrlSelector, codeSelector } from '../../selectors';
import RootState from '../../state';
import { Channel, Edition, Mode } from '../../types';
import { RequestsInProgress } from './sharedStateManagement';

const sliceName = 'output/gist';

const initialState: State = {
requestsInProgress: 0,
};

interface State extends RequestsInProgress {
interface State {
requestsInProgress: number;
id?: string;
url?: string;
code?: string;
Expand Down
68 changes: 52 additions & 16 deletions ui/frontend/reducers/output/macroExpansion.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { Action, ActionType } from '../../actions';
import { finish, start } from './sharedStateManagement';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import * as z from 'zod';

const DEFAULT: State = {
import { adaptFetchError, jsonPost, routes } from '../../actions';
import { macroExpansionRequestSelector } from '../../selectors';
import RootState from '../../state';

const sliceName = 'output/macroExpansion';

const initialState: State = {
requestsInProgress: 0,
};

Expand All @@ -12,17 +18,47 @@ interface State {
error?: string;
}

export default function macroExpansion(state = DEFAULT, action: Action) {
switch (action.type) {
case ActionType.RequestMacroExpansion:
return start(DEFAULT, state);
case ActionType.MacroExpansionSucceeded: {
const { stdout = '', stderr = '' } = action;
return finish(state, { stdout, stderr });
}
case ActionType.MacroExpansionFailed:
return finish(state, { error: action.error });
default:
return state;
}
interface MacroExpansionRequestBody {
code: string;
edition: string;
}

const MacroExpansionResponseBody = z.object({
success: z.boolean(),
stdout: z.string(),
stderr: z.string(),
});

type MacroExpansionResponseBody = z.infer<typeof MacroExpansionResponseBody>;

export const performMacroExpansion = createAsyncThunk<
MacroExpansionResponseBody,
void,
{ state: RootState }
>(sliceName, async (_arg: void, { getState }) => {
const body: MacroExpansionRequestBody = macroExpansionRequestSelector(getState());

const d = await adaptFetchError(() => jsonPost(routes.macroExpansion, body));
return MacroExpansionResponseBody.parseAsync(d);
});

const slice = createSlice({
name: sliceName,
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(performMacroExpansion.pending, (state) => {
state.requestsInProgress += 1;
})
.addCase(performMacroExpansion.fulfilled, (state, action) => {
state.requestsInProgress -= 1;
Object.assign(state, action.payload);
})
.addCase(performMacroExpansion.rejected, (state) => {
state.requestsInProgress -= 1;
});
},
});

export default slice.reducer;
Loading