Files
vscode-codeql/extensions/ql-vscode/src/view/method-modeling/MethodModelingView.tsx

110 lines
3.4 KiB
TypeScript

import * as React from "react";
import { useEffect, useMemo, useState } from "react";
import { MethodModeling } from "./MethodModeling";
import { getModelingStatus } from "../../model-editor/shared/modeling-status";
import { Method, canMethodBeModeled } from "../../model-editor/method";
import { ToMethodModelingMessage } from "../../common/interface-types";
import { assertNever } from "../../common/helpers-pure";
import { ModeledMethod } from "../../model-editor/modeled-method";
import { vscode } from "../vscode-api";
import { NotInModelingMode } from "./NotInModelingMode";
import { NoMethodSelected } from "./NoMethodSelected";
import { MethodModelingPanelViewState } from "../../model-editor/shared/view-state";
import { MethodAlreadyModeled } from "./MethodAlreadyModeled";
type Props = {
initialViewState?: MethodModelingPanelViewState;
};
export function MethodModelingView({ initialViewState }: Props): JSX.Element {
const [viewState, setViewState] = useState<
MethodModelingPanelViewState | undefined
>(initialViewState);
const [inModelingMode, setInModelingMode] = useState<boolean>(false);
const [method, setMethod] = useState<Method | undefined>(undefined);
const [modeledMethods, setModeledMethods] = useState<ModeledMethod[]>([]);
const [isMethodModified, setIsMethodModified] = useState<boolean>(false);
const modelingStatus = useMemo(
() => getModelingStatus(modeledMethods, isMethodModified),
[modeledMethods, isMethodModified],
);
useEffect(() => {
const listener = (evt: MessageEvent) => {
if (evt.origin === window.origin) {
const msg: ToMethodModelingMessage = evt.data;
switch (msg.t) {
case "setMethodModelingPanelViewState":
setViewState(msg.viewState);
break;
case "setInModelingMode":
setInModelingMode(msg.inModelingMode);
break;
case "setMethod":
setMethod(msg.method);
break;
case "setMultipleModeledMethods":
setModeledMethods(msg.modeledMethods);
break;
case "setMethodModified":
setIsMethodModified(msg.isModified);
break;
case "setSelectedMethod":
setMethod(msg.method);
setModeledMethods(msg.modeledMethods);
setIsMethodModified(msg.isModified);
break;
default:
assertNever(msg);
}
} else {
// sanitize origin
const origin = evt.origin.replace(/\n|\r/g, "");
console.error(`Invalid event origin ${origin}`);
}
};
window.addEventListener("message", listener);
return () => {
window.removeEventListener("message", listener);
};
}, []);
if (!inModelingMode) {
return <NotInModelingMode />;
}
if (!method) {
return <NoMethodSelected />;
}
if (!canMethodBeModeled(method, modeledMethods, isMethodModified)) {
return <MethodAlreadyModeled />;
}
const onChange = (
methodSignature: string,
modeledMethods: ModeledMethod[],
) => {
vscode.postMessage({
t: "setMultipleModeledMethods",
methodSignature,
modeledMethods,
});
};
return (
<MethodModeling
modelingStatus={modelingStatus}
method={method}
modeledMethods={modeledMethods}
showMultipleModels={viewState?.showMultipleModels}
onChange={onChange}
/>
);
}