Add type as modeled method type
This adds support for modeling types. A MaD language can now optionally define a `type` predicate. This allows internally propagating these models. The UI will now simply show a label "type" for type models without any way to edit these.
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
SinkModeledMethod,
|
||||
SourceModeledMethod,
|
||||
SummaryModeledMethod,
|
||||
TypeModeledMethod,
|
||||
} from "../modeled-method";
|
||||
import { DataTuple } from "../model-extension-file";
|
||||
import { Mode } from "../shared/mode";
|
||||
@@ -17,7 +18,7 @@ type ReadModeledMethod = (row: DataTuple[]) => ModeledMethod;
|
||||
|
||||
export type ModelsAsDataLanguagePredicate<T> = {
|
||||
extensiblePredicate: string;
|
||||
supportedKinds: string[];
|
||||
supportedKinds?: string[];
|
||||
generateMethodDefinition: GenerateMethodDefinition<T>;
|
||||
readModeledMethod: ReadModeledMethod;
|
||||
};
|
||||
@@ -43,6 +44,7 @@ export type ModelsAsDataLanguagePredicates = {
|
||||
sink?: ModelsAsDataLanguagePredicate<SinkModeledMethod>;
|
||||
summary?: ModelsAsDataLanguagePredicate<SummaryModeledMethod>;
|
||||
neutral?: ModelsAsDataLanguagePredicate<NeutralModeledMethod>;
|
||||
type?: ModelsAsDataLanguagePredicate<TypeModeledMethod>;
|
||||
};
|
||||
|
||||
export type ModelsAsDataLanguage = {
|
||||
|
||||
@@ -150,6 +150,30 @@ export const ruby: ModelsAsDataLanguage = {
|
||||
};
|
||||
},
|
||||
},
|
||||
type: {
|
||||
extensiblePredicate: "typeModel",
|
||||
// extensible predicate typeModel(string type1, string type2, string path);
|
||||
generateMethodDefinition: (method) => [
|
||||
method.relatedTypeName,
|
||||
method.typeName,
|
||||
`Method[${method.methodName}].${method.path}`,
|
||||
],
|
||||
readModeledMethod: (row) => {
|
||||
const typeName = row[1] as string;
|
||||
const { methodName, path } = parseRubyAccessPath(row[2] as string);
|
||||
|
||||
return {
|
||||
type: "type",
|
||||
relatedTypeName: row[0] as string,
|
||||
path,
|
||||
signature: rubyMethodSignature(typeName, methodName),
|
||||
packageName: "",
|
||||
typeName,
|
||||
methodName,
|
||||
methodParameters: "",
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
modelGeneration: {
|
||||
queryConstraints: {
|
||||
|
||||
@@ -25,6 +25,8 @@ export function createEmptyModeledMethod(
|
||||
return createEmptySummaryModeledMethod(canonicalMethodSignature);
|
||||
case "neutral":
|
||||
return createEmptyNeutralModeledMethod(canonicalMethodSignature);
|
||||
case "type":
|
||||
return createEmptyTypeModeledMethod(canonicalMethodSignature);
|
||||
default:
|
||||
assertNever(type);
|
||||
}
|
||||
@@ -86,3 +88,14 @@ function createEmptyNeutralModeledMethod(
|
||||
provenance: "manual",
|
||||
};
|
||||
}
|
||||
|
||||
function createEmptyTypeModeledMethod(
|
||||
methodSignature: MethodSignature,
|
||||
): ModeledMethod {
|
||||
return {
|
||||
...methodSignature,
|
||||
type: "type",
|
||||
relatedTypeName: "",
|
||||
path: "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ export type ModeledMethodType =
|
||||
| "source"
|
||||
| "sink"
|
||||
| "summary"
|
||||
| "type"
|
||||
| "neutral";
|
||||
|
||||
export type Provenance =
|
||||
@@ -51,12 +52,19 @@ export interface NeutralModeledMethod extends MethodSignature {
|
||||
readonly provenance: Provenance;
|
||||
}
|
||||
|
||||
export interface TypeModeledMethod extends MethodSignature {
|
||||
readonly type: "type";
|
||||
readonly relatedTypeName: string;
|
||||
readonly path: string;
|
||||
}
|
||||
|
||||
export type ModeledMethod =
|
||||
| NoneModeledMethod
|
||||
| SourceModeledMethod
|
||||
| SinkModeledMethod
|
||||
| SummaryModeledMethod
|
||||
| NeutralModeledMethod;
|
||||
| NeutralModeledMethod
|
||||
| TypeModeledMethod;
|
||||
|
||||
export type ModeledMethodKind = string;
|
||||
|
||||
|
||||
@@ -70,6 +70,13 @@ function canonicalizeModeledMethod(
|
||||
kind: modeledMethod.kind,
|
||||
provenance: "manual",
|
||||
};
|
||||
case "type":
|
||||
return {
|
||||
...methodSignature,
|
||||
type: "type",
|
||||
relatedTypeName: modeledMethod.relatedTypeName,
|
||||
path: modeledMethod.path,
|
||||
};
|
||||
default:
|
||||
assertNever(modeledMethod);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
SinkModeledMethod,
|
||||
SourceModeledMethod,
|
||||
SummaryModeledMethod,
|
||||
TypeModeledMethod,
|
||||
} from "./modeled-method";
|
||||
import {
|
||||
getModelsAsDataLanguage,
|
||||
@@ -68,6 +69,7 @@ export function createDataExtensionYaml(
|
||||
sink: [] as SinkModeledMethod[],
|
||||
summary: [] as SummaryModeledMethod[],
|
||||
neutral: [] as NeutralModeledMethod[],
|
||||
type: [] as TypeModeledMethod[],
|
||||
} satisfies Record<keyof ModelsAsDataLanguagePredicates, ModeledMethod[]>;
|
||||
|
||||
for (const modeledMethod of modeledMethods) {
|
||||
@@ -88,6 +90,9 @@ export function createDataExtensionYaml(
|
||||
case "neutral":
|
||||
methodsByType.neutral.push(modeledMethod);
|
||||
break;
|
||||
case "type":
|
||||
methodsByType.type.push(modeledMethod);
|
||||
break;
|
||||
default:
|
||||
assertNever(modeledMethod);
|
||||
}
|
||||
@@ -122,6 +127,12 @@ export function createDataExtensionYaml(
|
||||
methodsByType.neutral,
|
||||
modelsAsDataLanguage.predicates.neutral,
|
||||
);
|
||||
case "type":
|
||||
return createExtensions(
|
||||
language,
|
||||
methodsByType.type,
|
||||
modelsAsDataLanguage.predicates.type,
|
||||
);
|
||||
default:
|
||||
assertNever(type);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,14 @@ export const ModelTypeDropdown = ({
|
||||
[onChange, method, modeledMethod, argumentsList],
|
||||
);
|
||||
|
||||
const value = modeledMethod?.type ?? "none";
|
||||
|
||||
const isShownOption = options.some((option) => option.value === value);
|
||||
|
||||
if (!isShownOption) {
|
||||
return <>{value}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
value={modeledMethod?.type ?? "none"}
|
||||
|
||||
@@ -75,33 +75,71 @@ describe("parseGenerateModelResults", () => {
|
||||
ruby,
|
||||
createMockLogger(),
|
||||
);
|
||||
expect(result.sort()).toEqual(
|
||||
[
|
||||
{
|
||||
input: "Argument[self]",
|
||||
kind: "value",
|
||||
methodName: "create_function",
|
||||
methodParameters: "",
|
||||
output: "ReturnValue",
|
||||
packageName: "",
|
||||
provenance: "manual",
|
||||
signature: "SQLite3::Database#create_function",
|
||||
type: "summary",
|
||||
typeName: "SQLite3::Database",
|
||||
},
|
||||
{
|
||||
input: "Argument[1]",
|
||||
kind: "value",
|
||||
methodName: "new",
|
||||
methodParameters: "",
|
||||
output: "ReturnValue",
|
||||
packageName: "",
|
||||
provenance: "manual",
|
||||
signature: "SQLite3::Value!#new",
|
||||
type: "summary",
|
||||
typeName: "SQLite3::Value!",
|
||||
},
|
||||
].sort(),
|
||||
);
|
||||
expect(result).toEqual([
|
||||
{
|
||||
methodName: "types",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::ResultSet#types",
|
||||
type: "type",
|
||||
typeName: "SQLite3::ResultSet",
|
||||
},
|
||||
{
|
||||
methodName: "columns",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::ResultSet#columns",
|
||||
type: "type",
|
||||
typeName: "SQLite3::ResultSet",
|
||||
},
|
||||
{
|
||||
methodName: "types",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::Statement#types",
|
||||
type: "type",
|
||||
typeName: "SQLite3::Statement",
|
||||
},
|
||||
{
|
||||
methodName: "columns",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::Statement#columns",
|
||||
type: "type",
|
||||
typeName: "SQLite3::Statement",
|
||||
},
|
||||
{
|
||||
input: "Argument[self]",
|
||||
kind: "value",
|
||||
methodName: "create_function",
|
||||
methodParameters: "",
|
||||
output: "ReturnValue",
|
||||
packageName: "",
|
||||
provenance: "manual",
|
||||
signature: "SQLite3::Database#create_function",
|
||||
type: "summary",
|
||||
typeName: "SQLite3::Database",
|
||||
},
|
||||
{
|
||||
input: "Argument[1]",
|
||||
kind: "value",
|
||||
methodName: "new",
|
||||
methodParameters: "",
|
||||
output: "ReturnValue",
|
||||
packageName: "",
|
||||
provenance: "manual",
|
||||
signature: "SQLite3::Value!#new",
|
||||
type: "summary",
|
||||
typeName: "SQLite3::Value!",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -138,6 +138,46 @@ describe("runGenerateQueries", () => {
|
||||
...options,
|
||||
});
|
||||
expect(onResults).toHaveBeenCalledWith([
|
||||
{
|
||||
methodName: "types",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::ResultSet#types",
|
||||
type: "type",
|
||||
typeName: "SQLite3::ResultSet",
|
||||
},
|
||||
{
|
||||
methodName: "columns",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::ResultSet#columns",
|
||||
type: "type",
|
||||
typeName: "SQLite3::ResultSet",
|
||||
},
|
||||
{
|
||||
methodName: "types",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::Statement#types",
|
||||
type: "type",
|
||||
typeName: "SQLite3::Statement",
|
||||
},
|
||||
{
|
||||
methodName: "columns",
|
||||
methodParameters: "",
|
||||
packageName: "",
|
||||
path: "ReturnValue",
|
||||
relatedTypeName: "Array",
|
||||
signature: "SQLite3::Statement#columns",
|
||||
type: "type",
|
||||
typeName: "SQLite3::Statement",
|
||||
},
|
||||
{
|
||||
input: "Argument[self]",
|
||||
kind: "value",
|
||||
|
||||
Reference in New Issue
Block a user