Merge pull request #2600 from github/robertbrignull/data-supported

Show more clearly when a method is already modeled
This commit is contained in:
Robert
2023-07-12 17:26:10 +01:00
committed by GitHub

View File

@@ -39,6 +39,14 @@ const ViewLink = styled(VSCodeLink)`
white-space: nowrap; white-space: nowrap;
`; `;
const modelTypeOptions = [
{ value: "none", label: "Unmodeled" },
{ value: "source", label: "Source" },
{ value: "sink", label: "Sink" },
{ value: "summary", label: "Flow summary" },
{ value: "neutral", label: "Neutral" },
];
type Props = { type Props = {
externalApiUsage: ExternalApiUsage; externalApiUsage: ExternalApiUsage;
modeledMethod: ModeledMethod | undefined; modeledMethod: ModeledMethod | undefined;
@@ -49,12 +57,23 @@ type Props = {
) => void; ) => void;
}; };
export const MethodRow = ({ export const MethodRow = (props: Props) => {
externalApiUsage, const { externalApiUsage, modeledMethod } = props;
modeledMethod,
mode, const methodCanBeModeled =
onChange, !externalApiUsage.supported ||
}: Props) => { (modeledMethod && modeledMethod?.type !== "none");
if (methodCanBeModeled) {
return <ModelableMethodRow {...props} />;
} else {
return <UnmodelableMethodRow {...props} />;
}
};
function ModelableMethodRow(props: Props) {
const { externalApiUsage, modeledMethod, mode, onChange } = props;
const argumentsList = useMemo(() => { const argumentsList = useMemo(() => {
if (externalApiUsage.methodParameters === "()") { if (externalApiUsage.methodParameters === "()") {
return []; return [];
@@ -129,35 +148,11 @@ export const MethodRow = ({
[onChange, externalApiUsage, modeledMethod], [onChange, externalApiUsage, modeledMethod],
); );
const jumpToUsage = useCallback(() => { const jumpToUsage = useCallback(
vscode.postMessage({ () => sendJumpToUsageMessage(externalApiUsage),
t: "jumpToUsage", [externalApiUsage],
// In framework mode, the first and only usage is the definition of the method
location: externalApiUsage.usages[0].url,
});
}, [externalApiUsage]);
const predicate =
modeledMethod?.type && modeledMethod.type !== "none"
? extensiblePredicateDefinitions[modeledMethod.type]
: undefined;
const showModelTypeCell =
!externalApiUsage.supported ||
(modeledMethod && modeledMethod?.type !== "none");
const modelTypeOptions = useMemo(
() => [
{ value: "none", label: "Unmodeled" },
{ value: "source", label: "Source" },
{ value: "sink", label: "Sink" },
{ value: "summary", label: "Flow summary" },
{ value: "neutral", label: "Neutral" },
],
[],
); );
const showInputCell =
modeledMethod?.type && ["sink", "summary"].includes(modeledMethod?.type);
const inputOptions = useMemo( const inputOptions = useMemo(
() => [ () => [
{ value: "Argument[this]", label: "Argument[this]" }, { value: "Argument[this]", label: "Argument[this]" },
@@ -169,8 +164,6 @@ export const MethodRow = ({
[argumentsList], [argumentsList],
); );
const showOutputCell =
modeledMethod?.type && ["source", "summary"].includes(modeledMethod?.type);
const outputOptions = useMemo( const outputOptions = useMemo(
() => [ () => [
{ value: "ReturnValue", label: "ReturnValue" }, { value: "ReturnValue", label: "ReturnValue" },
@@ -183,17 +176,21 @@ export const MethodRow = ({
[argumentsList], [argumentsList],
); );
const showInputCell =
modeledMethod?.type && ["sink", "summary"].includes(modeledMethod?.type);
const showOutputCell =
modeledMethod?.type && ["source", "summary"].includes(modeledMethod?.type);
const predicate =
modeledMethod?.type && modeledMethod.type !== "none"
? extensiblePredicateDefinitions[modeledMethod.type]
: undefined;
const showKindCell = predicate?.supportedKinds; const showKindCell = predicate?.supportedKinds;
return ( return (
<VSCodeDataGridRow> <VSCodeDataGridRow>
<ApiOrMethodCell gridColumn={1}> <ApiOrMethodCell gridColumn={1}>
<VSCodeCheckbox /> <VSCodeCheckbox />
<span> <ExternalApiUsageName {...props} />
{externalApiUsage.packageName}.{externalApiUsage.typeName}.
{externalApiUsage.methodName}
{externalApiUsage.methodParameters}
</span>
{mode === Mode.Application && ( {mode === Mode.Application && (
<UsagesButton onClick={jumpToUsage}> <UsagesButton onClick={jumpToUsage}>
{externalApiUsage.usages.length} {externalApiUsage.usages.length}
@@ -205,7 +202,6 @@ export const MethodRow = ({
<Dropdown <Dropdown
value={modeledMethod?.type ?? "none"} value={modeledMethod?.type ?? "none"}
options={modelTypeOptions} options={modelTypeOptions}
disabled={!showModelTypeCell}
onChange={handleTypeInput} onChange={handleTypeInput}
/> />
</VSCodeDataGridCell> </VSCodeDataGridCell>
@@ -235,4 +231,52 @@ export const MethodRow = ({
</VSCodeDataGridCell> </VSCodeDataGridCell>
</VSCodeDataGridRow> </VSCodeDataGridRow>
); );
}; }
function UnmodelableMethodRow(props: {
externalApiUsage: ExternalApiUsage;
mode: Mode;
}) {
const { externalApiUsage, mode } = props;
const jumpToUsage = useCallback(
() => sendJumpToUsageMessage(externalApiUsage),
[externalApiUsage],
);
return (
<VSCodeDataGridRow>
<ApiOrMethodCell gridColumn={1}>
<VSCodeCheckbox />
<ExternalApiUsageName {...props} />
{mode === Mode.Application && (
<UsagesButton onClick={jumpToUsage}>
{externalApiUsage.usages.length}
</UsagesButton>
)}
<ViewLink onClick={jumpToUsage}>View</ViewLink>
</ApiOrMethodCell>
<VSCodeDataGridCell gridColumn="span 4">
Method already modeled by CodeQL or a different extension pack
</VSCodeDataGridCell>
</VSCodeDataGridRow>
);
}
function ExternalApiUsageName(props: { externalApiUsage: ExternalApiUsage }) {
return (
<span>
{props.externalApiUsage.packageName}.{props.externalApiUsage.typeName}.
{props.externalApiUsage.methodName}
{props.externalApiUsage.methodParameters}
</span>
);
}
function sendJumpToUsageMessage(externalApiUsage: ExternalApiUsage) {
vscode.postMessage({
t: "jumpToUsage",
// In framework mode, the first and only usage is the definition of the method
location: externalApiUsage.usages[0].url,
});
}