Skip to content

Commit

Permalink
Fix ancestor types missing their concrete descendant type names
Browse files Browse the repository at this point in the history
  • Loading branch information
CarsonF committed Sep 3, 2024
1 parent b4dfe85 commit 319a2cf
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 13 deletions.
6 changes: 5 additions & 1 deletion integration-tests/lts/dbschema/default.esdl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ module default {
property character_name -> str;
}

abstract type Person {
abstract type LivingThing {
age: int32;
}

abstract type Person extending LivingThing {
required property name -> str {
constraint exclusive;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE MIGRATION m173ddshjvgy5ampp7rzi2g7cwwdkaljvlifemr5vugnkimtbpp6ca
ONTO m1wb2dgjeppqex272zwvqnsdfzdvvppub4iwa5vaxu3xxigyjlruka
{
CREATE ABSTRACT TYPE default::LivingThing {
CREATE PROPERTY age: std::int32;
};
ALTER TYPE default::Person EXTENDING default::LivingThing LAST;
};
22 changes: 21 additions & 1 deletion integration-tests/lts/select.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,16 +348,18 @@ describe("select", () => {
...e.is(e.Hero, e.Hero["*"]),
name: true,
}));
type result = $infer<typeof q>;

// 'id' is filtered out since it is not valid in a polymorphic expr
tc.assert<
tc.IsExact<
$infer<typeof q>,
result,
({ name: string } & (
| { __typename: "default::Villain" }
| {
__typename: "default::Hero";
height: string | null;
age: number | null;
isAdult: boolean | null;
number_of_movies: number | null;
secret_identity: string | null;
Expand All @@ -374,6 +376,24 @@ describe("select", () => {
tc.assert<tc.IsExact<typeof name, "default::Hero">>(true);
});

test("polymorphic type names", () => {
tc.assert<
tc.IsExact<
typeof e.LivingThing.__element__.__polyTypenames__,
"default::Hero" | "default::Villain"
>
>(true);
tc.assert<
tc.IsExact<
typeof e.Person.__element__.__polyTypenames__,
"default::Hero" | "default::Villain"
>
>(true);
tc.assert<
tc.IsExact<typeof e.Hero.__element__.__polyTypenames__, "default::Hero">
>(true);
});

test("limit/offset inference", () => {
const testSet = e.set(1, 2, 3);

Expand Down
35 changes: 24 additions & 11 deletions packages/generate/src/edgeql-js/generateObjectTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,7 @@ export const getStringRepresentation: (
export const generateObjectTypes = (params: GeneratorParams) => {
const { dir, types } = params;

const descendents = new Map<string, Set<string>>();
for (const type of types.values()) {
if (type.kind === "object" && !type.is_abstract) {
for (const base of type.bases) {
if (!descendents.has(base.id)) {
descendents.set(base.id, new Set());
}
descendents.get(base.id)!.add(type.name);
}
}
}
const descendents = generatePolyTypenames(types);

for (const type of types.values()) {
if (type.kind !== "object") {
Expand Down Expand Up @@ -393,3 +383,26 @@ export const generateObjectTypes = (params: GeneratorParams) => {
body.addToDefaultExport(literal, name);
}
};

function generatePolyTypenames(types: $.introspect.Types) {
const descendents = new Map<string, Set<string>>();

const visit = (current: $.introspect.Type, descendent: $.introspect.Type) => {
if (current.kind !== "object") {
return;
}
for (const base of current.bases) {
if (!descendents.has(base.id)) {
descendents.set(base.id, new Set());
}
descendents.get(base.id)!.add(descendent.name);
visit(types.get(base.id), descendent);
}
};
for (const type of types.values()) {
if (type.kind === "object" && !type.is_abstract) {
visit(type, type);
}
}
return descendents;
}

0 comments on commit 319a2cf

Please sign in to comment.