Merge pull request #2600 from github/robertbrignull/data-supported
Show more clearly when a method is already modeled
This commit is contained in:
@@ -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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user