Merge pull request #2942 from github/robertbrignull/SetModeledMethodsMessage

Convert SetModeledMethodsMessage to include multiple modeled methods
This commit is contained in:
Robert
2023-10-11 11:45:57 +01:00
committed by GitHub
14 changed files with 202 additions and 200 deletions

View File

@@ -507,7 +507,7 @@ interface SetMethodsMessage {
interface SetModeledMethodsMessage {
t: "setModeledMethods";
methods: Record<string, ModeledMethod>;
methods: Record<string, ModeledMethod[]>;
}
interface SetModifiedMethodsMessage {

View File

@@ -68,12 +68,12 @@ export function getArgumentsList(methodParameters: string): string[] {
export function canMethodBeModeled(
method: Method,
modeledMethod: ModeledMethod | undefined,
modeledMethods: ModeledMethod[],
methodIsUnsaved: boolean,
): boolean {
return (
!method.supported ||
(modeledMethod && modeledMethod?.type !== "none") ||
modeledMethods.some((modeledMethod) => modeledMethod.type !== "none") ||
methodIsUnsaved
);
}

View File

@@ -43,10 +43,7 @@ import { AutoModeler } from "./auto-modeler";
import { telemetryListener } from "../common/vscode/telemetry";
import { ModelingStore } from "./modeling-store";
import { ModelEditorViewTracker } from "./model-editor-view-tracker";
import {
convertFromLegacyModeledMethod,
convertToLegacyModeledMethods,
} from "./shared/modeled-methods-legacy";
import { convertFromLegacyModeledMethod } from "./shared/modeled-methods-legacy";
export class ModelEditorView extends AbstractWebview<
ToModelEditorMessage,
@@ -640,7 +637,7 @@ export class ModelEditorView extends AbstractWebview<
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
await this.postMessage({
t: "setModeledMethods",
methods: convertToLegacyModeledMethods(event.modeledMethods),
methods: event.modeledMethods,
});
}
}),

View File

@@ -1,32 +1,5 @@
import { ModeledMethod } from "../modeled-method";
/**
* Converts a record of a single ModeledMethod indexed by signature to a record of ModeledMethod[] indexed by signature
* for legacy usage. This function should always be used instead of the trivial conversion to track usages of this
* conversion.
*
* This method should only be called inside a `postMessage` call. If it's used anywhere else, consider whether the
* boundary is correct: the boundary should as close as possible to the extension host -> webview boundary.
*
* @param modeledMethods The record of a single ModeledMethod indexed by signature
*/
export function convertToLegacyModeledMethods(
modeledMethods: Record<string, ModeledMethod[]>,
): Record<string, ModeledMethod> {
// Always take the first modeled method in the array
return Object.fromEntries(
Object.entries(modeledMethods)
.map(([signature, modeledMethods]) => {
const modeledMethod = convertToLegacyModeledMethod(modeledMethods);
if (!modeledMethod) {
return null;
}
return [signature, modeledMethod];
})
.filter((entry): entry is [string, ModeledMethod] => entry !== null),
);
}
/**
* Converts a single ModeledMethod to a ModeledMethod[] for legacy usage. This function should always be used instead
* of the trivial conversion to track usages of this conversion.

View File

@@ -146,8 +146,9 @@ LibraryRow.args = {
],
},
],
modeledMethods: {
"org.sql2o.Sql2o#Sql2o(String)": {
modeledMethodsMap: {
"org.sql2o.Sql2o#Sql2o(String)": [
{
type: "sink",
input: "Argument[0]",
output: "",
@@ -159,7 +160,9 @@ LibraryRow.args = {
methodName: "Sql2o",
methodParameters: "(String)",
},
"org.sql2o.Connection#createQuery(String)": {
],
"org.sql2o.Connection#createQuery(String)": [
{
type: "summary",
input: "Argument[this]",
output: "ReturnValue",
@@ -171,7 +174,9 @@ LibraryRow.args = {
methodName: "createQuery",
methodParameters: "(String)",
},
"org.sql2o.Sql2o#open()": {
],
"org.sql2o.Sql2o#open()": [
{
type: "summary",
input: "Argument[this]",
output: "ReturnValue",
@@ -183,7 +188,9 @@ LibraryRow.args = {
methodName: "open",
methodParameters: "()",
},
"org.sql2o.Query#executeScalar(Class)": {
],
"org.sql2o.Query#executeScalar(Class)": [
{
type: "neutral",
input: "",
output: "",
@@ -195,7 +202,9 @@ LibraryRow.args = {
methodName: "executeScalar",
methodParameters: "(Class)",
},
"org.sql2o.Sql2o#Sql2o(String,String,String)": {
],
"org.sql2o.Sql2o#Sql2o(String,String,String)": [
{
type: "neutral",
input: "",
output: "",
@@ -207,6 +216,7 @@ LibraryRow.args = {
methodName: "Sql2o",
methodParameters: "(String,String,String)",
},
],
},
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
inProgressMethods: new InProgressMethods(),

View File

@@ -216,7 +216,8 @@ ModelEditor.args = {
},
],
initialModeledMethods: {
"org.sql2o.Sql2o#Sql2o(String)": {
"org.sql2o.Sql2o#Sql2o(String)": [
{
type: "sink",
input: "Argument[0]",
output: "",
@@ -228,7 +229,9 @@ ModelEditor.args = {
methodName: "Sql2o",
methodParameters: "(String)",
},
"org.sql2o.Connection#createQuery(String)": {
],
"org.sql2o.Connection#createQuery(String)": [
{
type: "summary",
input: "Argument[this]",
output: "ReturnValue",
@@ -240,7 +243,9 @@ ModelEditor.args = {
methodName: "createQuery",
methodParameters: "(String)",
},
"org.sql2o.Sql2o#open()": {
],
"org.sql2o.Sql2o#open()": [
{
type: "summary",
input: "Argument[this]",
output: "ReturnValue",
@@ -252,7 +257,9 @@ ModelEditor.args = {
methodName: "open",
methodParameters: "()",
},
"org.sql2o.Query#executeScalar(Class)": {
],
"org.sql2o.Query#executeScalar(Class)": [
{
type: "neutral",
input: "",
output: "",
@@ -264,7 +271,9 @@ ModelEditor.args = {
methodName: "executeScalar",
methodParameters: "(Class)",
},
"org.sql2o.Sql2o#Sql2o(String,String,String)": {
],
"org.sql2o.Sql2o#Sql2o(String,String,String)": [
{
type: "neutral",
input: "",
output: "",
@@ -276,5 +285,6 @@ ModelEditor.args = {
methodName: "Sql2o",
methodParameters: "(String,String,String)",
},
],
},
};

View File

@@ -89,7 +89,13 @@ export function MethodModelingView({ initialViewState }: Props): JSX.Element {
return <NoMethodSelected />;
}
if (!canMethodBeModeled(method, modeledMethod, isMethodModified)) {
if (
!canMethodBeModeled(
method,
convertFromLegacyModeledMethod(modeledMethod),
isMethodModified,
)
) {
return <MethodAlreadyModeled />;
}

View File

@@ -71,7 +71,7 @@ export type LibraryRowProps = {
title: string;
libraryVersion?: string;
methods: Method[];
modeledMethods: Record<string, ModeledMethod>;
modeledMethodsMap: Record<string, ModeledMethod[]>;
modifiedSignatures: Set<string>;
inProgressMethods: InProgressMethods;
viewState: ModelEditorViewState;
@@ -92,7 +92,7 @@ export const LibraryRow = ({
title,
libraryVersion,
methods,
modeledMethods,
modeledMethodsMap,
modifiedSignatures,
inProgressMethods,
viewState,
@@ -231,7 +231,7 @@ export const LibraryRow = ({
<ModeledMethodDataGrid
packageName={title}
methods={methods}
modeledMethods={modeledMethods}
modeledMethodsMap={modeledMethodsMap}
modifiedSignatures={modifiedSignatures}
inProgressMethods={inProgressMethods}
viewState={viewState}

View File

@@ -74,7 +74,7 @@ const ButtonsContainer = styled.div`
type Props = {
initialViewState?: ModelEditorViewState;
initialMethods?: Method[];
initialModeledMethods?: Record<string, ModeledMethod>;
initialModeledMethods?: Record<string, ModeledMethod[]>;
initialHideModeledMethods?: boolean;
};
@@ -113,7 +113,7 @@ export function ModelEditor({
}, [hideModeledMethods]);
const [modeledMethods, setModeledMethods] = useState<
Record<string, ModeledMethod>
Record<string, ModeledMethod[]>
>(initialModeledMethods);
useEffect(() => {
@@ -329,7 +329,7 @@ export function ModelEditor({
</ButtonsContainer>
<ModeledMethodsList
methods={methods}
modeledMethods={modeledMethods}
modeledMethodsMap={modeledMethods}
modifiedSignatures={modifiedSignatures}
inProgressMethods={inProgressMethods}
viewState={viewState}

View File

@@ -18,7 +18,7 @@ export const GRID_TEMPLATE_COLUMNS = "0.5fr 0.125fr 0.125fr 0.125fr 0.125fr";
export type ModeledMethodDataGridProps = {
packageName: string;
methods: Method[];
modeledMethods: Record<string, ModeledMethod>;
modeledMethodsMap: Record<string, ModeledMethod[]>;
modifiedSignatures: Set<string>;
inProgressMethods: InProgressMethods;
viewState: ModelEditorViewState;
@@ -30,7 +30,7 @@ export type ModeledMethodDataGridProps = {
export const ModeledMethodDataGrid = ({
packageName,
methods,
modeledMethods,
modeledMethodsMap,
modifiedSignatures,
inProgressMethods,
viewState,
@@ -45,11 +45,11 @@ export const ModeledMethodDataGrid = ({
const methodsWithModelability = [];
let numHiddenMethods = 0;
for (const method of sortMethods(methods)) {
const modeledMethod = modeledMethods[method.signature];
const modeledMethods = modeledMethodsMap[method.signature] ?? [];
const methodIsUnsaved = modifiedSignatures.has(method.signature);
const methodCanBeModeled = canMethodBeModeled(
method,
modeledMethod,
modeledMethods,
methodIsUnsaved,
);
@@ -60,7 +60,7 @@ export const ModeledMethodDataGrid = ({
}
}
return [methodsWithModelability, numHiddenMethods];
}, [hideModeledMethods, methods, modeledMethods, modifiedSignatures]);
}, [hideModeledMethods, methods, modeledMethodsMap, modifiedSignatures]);
const someMethodsAreVisible = methodsWithModelability.length > 0;
@@ -86,13 +86,13 @@ export const ModeledMethodDataGrid = ({
</VSCodeDataGridCell>
</VSCodeDataGridRow>
{methodsWithModelability.map(({ method, methodCanBeModeled }) => {
const modeledMethod = modeledMethods[method.signature];
const modeledMethods = modeledMethodsMap[method.signature] ?? [];
return (
<MethodRow
key={method.signature}
method={method}
methodCanBeModeled={methodCanBeModeled}
modeledMethods={modeledMethod ? [modeledMethod] : []}
modeledMethods={modeledMethods}
methodIsUnsaved={modifiedSignatures.has(method.signature)}
modelingInProgress={inProgressMethods.hasMethod(
packageName,

View File

@@ -13,7 +13,7 @@ import { InProgressMethods } from "../../model-editor/shared/in-progress-methods
export type ModeledMethodsListProps = {
methods: Method[];
modeledMethods: Record<string, ModeledMethod>;
modeledMethodsMap: Record<string, ModeledMethod[]>;
modifiedSignatures: Set<string>;
inProgressMethods: InProgressMethods;
revealedMethodSignature: string | null;
@@ -36,7 +36,7 @@ const libraryNameOverrides: Record<string, string> = {
export const ModeledMethodsList = ({
methods,
modeledMethods,
modeledMethodsMap,
modifiedSignatures,
inProgressMethods,
viewState,
@@ -82,7 +82,7 @@ export const ModeledMethodsList = ({
title={libraryNameOverrides[libraryName] ?? libraryName}
libraryVersion={libraryVersions[libraryName]}
methods={grouped[libraryName]}
modeledMethods={modeledMethods}
modeledMethodsMap={modeledMethodsMap}
modifiedSignatures={modifiedSignatures}
inProgressMethods={inProgressMethods}
viewState={viewState}

View File

@@ -30,8 +30,9 @@ describe(LibraryRow.name, () => {
title="sql2o"
libraryVersion="1.6.0"
methods={[method]}
modeledMethods={{
[method.signature]: {
modeledMethodsMap={{
[method.signature]: [
{
...method,
type: "sink",
input: "Argument[0]",
@@ -39,6 +40,7 @@ describe(LibraryRow.name, () => {
kind: "jndi-injection",
provenance: "df-generated",
},
],
}}
modifiedSignatures={new Set([method.signature])}
inProgressMethods={new InProgressMethods()}

View File

@@ -56,8 +56,9 @@ describe(ModeledMethodDataGrid.name, () => {
<ModeledMethodDataGrid
packageName="sql2o"
methods={[method1, method2, method3]}
modeledMethods={{
[method1.signature]: {
modeledMethodsMap={{
[method1.signature]: [
{
...method1,
type: "sink",
input: "Argument[0]",
@@ -65,6 +66,7 @@ describe(ModeledMethodDataGrid.name, () => {
kind: "jndi-injection",
provenance: "df-generated",
},
],
}}
modifiedSignatures={new Set([method1.signature])}
inProgressMethods={new InProgressMethods()}

View File

@@ -56,8 +56,9 @@ describe(ModeledMethodsList.name, () => {
reactRender(
<ModeledMethodsList
methods={[method1, method2, method3]}
modeledMethods={{
[method1.signature]: {
modeledMethodsMap={{
[method1.signature]: [
{
...method1,
type: "sink",
input: "Argument[0]",
@@ -65,6 +66,7 @@ describe(ModeledMethodsList.name, () => {
kind: "jndi-injection",
provenance: "df-generated",
},
],
}}
modifiedSignatures={new Set([method1.signature])}
inProgressMethods={new InProgressMethods()}