Skip to content

Commit

Permalink
Support circular inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
runem committed Nov 29, 2019
1 parent 6574e9d commit cc4bc49
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/analyze/stages/flavor/visit-inheritance.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { Node } from "typescript";
import { InheritanceTreeClause, InheritanceTreeNode } from "../../types/inheritance-tree";
import { AnalyzerVisitContext } from "../../analyzer-visit-context";
import { InheritanceTreeClause, InheritanceTreeNode } from "../../types/inheritance-tree";
import { executeFunctionsUntilMatch } from "../../util/execute-functions-until-match";

export function visitAndExpandInheritClause(inheritClause: InheritanceTreeClause, context: AnalyzerVisitContext): InheritanceTreeClause {
export function visitAndExpandInheritClause(
inheritClause: InheritanceTreeClause,
context: AnalyzerVisitContext,
visitSet: Set<Node>
): InheritanceTreeClause {
const resolved = (() => {
if (inheritClause.resolved == null) return undefined;

return inheritClause.resolved.map(resolved => {
let inheritance: InheritanceTreeClause[] = [];
visitInheritance(resolved.node, context, results => {
inheritance = inheritance.concat(results);
});
visitInheritance(
resolved.node,
context,
results => {
inheritance = inheritance.concat(results);
},
visitSet
);

return {
...resolved,
Expand All @@ -22,22 +31,30 @@ export function visitAndExpandInheritClause(inheritClause: InheritanceTreeClause

return {
...inheritClause,
horizontalInherits: inheritClause.horizontalInherits?.map(arg => visitAndExpandInheritClause(arg, context)),
horizontalInherits: inheritClause.horizontalInherits?.map(arg => visitAndExpandInheritClause(arg, context, visitSet)),
resolved
};
}

export function visitInheritance(node: Node, context: AnalyzerVisitContext, emit: (results: InheritanceTreeClause[]) => void): void {
export function visitInheritance(
node: Node,
context: AnalyzerVisitContext,
emit: (results: InheritanceTreeClause[]) => void,
visitSet?: Set<Node>
): void {
visitSet = visitSet || new Set();

if (visitSet.has(node)) {
return;
}

visitSet.add(node);

const result = executeFunctionsUntilMatch(context.flavors, "discoverInheritance", node, context);

if (result != null) {
emit(result.value.map(link => visitAndExpandInheritClause(link, context)));
emit(result.value.map(link => visitAndExpandInheritClause(link, context, visitSet!)));

if (!result.shouldContinue) return;
}

// Visit child nodes
/*node.forEachChild(child => {
visitInheritance2(child, context, emit);
});*/
}
49 changes: 49 additions & 0 deletions test/flavors/custom-element/mixin-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,55 @@ import test from "ava";
import { analyzeText } from "../../../src/analyze/analyze-text";
import { getAttributeNames, getComponentProp, getPropertyNames } from "../../helpers/util";

test("Handles circular inheritance", t => {
const { result } = analyzeText(`
class MyElement extends MyElement {
}
/**
* @element
*/
class MyElement extends MyBase {
static get observedAttributes() {
return ["a", "b"];
}
}
`);

const { members } = result.componentDefinitions[0]?.declaration();

const attributeNames = getAttributeNames(members);

t.deepEqual(attributeNames, ["a", "b"]);
});

test("Handles circular inheritance using mixins", t => {
const { result } = analyzeText(`
const Mixin1 = (Base) => {
return class Mixin1 extends Mixin2(Base) {}
}
const Mixin2 = (Base) => {
return class Mixin2 extends Mixin1(Base) {}
}
/**
* @element
*/
class MyElement extends Mixin1(Mixin2(HTMLElement)) {
static get observedAttributes() {
return ["a", "b"];
}
}
`);

const { members } = result.componentDefinitions[0]?.declaration();

const attributeNames = getAttributeNames(members);

t.deepEqual(attributeNames, ["a", "b"]);
});

test("Handles simple mixin", t => {
const { result } = analyzeText(`
const MyMixin = (Base) => {
Expand Down

0 comments on commit cc4bc49

Please sign in to comment.