From 40db3cdfa311e5316f1d13112548b09fcbdf1ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dandelion=20Man=C3=A9?= Date: Thu, 28 Jun 2018 14:57:23 -0700 Subject: [PATCH] Add `RelationalView.match` (#438) `match` implements pattern matching over `Entity` Test plan: Unit tests included. --- src/v3/plugins/github/relationalView.js | 30 ++++++++++++++++++++ src/v3/plugins/github/relationalView.test.js | 19 +++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/v3/plugins/github/relationalView.js b/src/v3/plugins/github/relationalView.js index d67cc43..9bd7efe 100644 --- a/src/v3/plugins/github/relationalView.js +++ b/src/v3/plugins/github/relationalView.js @@ -690,6 +690,36 @@ function* getAuthors( } } +export type MatchHandlers = {| + +repo: (x: Repo) => T, + +issue: (x: Issue) => T, + +pull: (x: Pull) => T, + +review: (x: Review) => T, + +comment: (x: Comment) => T, + +userlike: (x: Userlike) => T, +|}; +export function match(handlers: MatchHandlers, x: Entity): T { + if (x instanceof Repo) { + return handlers.repo(x); + } + if (x instanceof Issue) { + return handlers.issue(x); + } + if (x instanceof Pull) { + return handlers.pull(x); + } + if (x instanceof Review) { + return handlers.review(x); + } + if (x instanceof Comment) { + return handlers.comment(x); + } + if (x instanceof Userlike) { + return handlers.userlike(x); + } + throw new Error(`Unexpected entity ${x}`); +} + export type Entity = Repo | Issue | Pull | Review | Comment | Userlike; export type AuthoredEntity = Issue | Pull | Review | Comment; export type TextContentEntity = Issue | Pull | Review | Comment; diff --git a/src/v3/plugins/github/relationalView.test.js b/src/v3/plugins/github/relationalView.test.js index 3578da2..da53373 100644 --- a/src/v3/plugins/github/relationalView.test.js +++ b/src/v3/plugins/github/relationalView.test.js @@ -138,6 +138,25 @@ describe("plugins/github/relationalView", () => { has("url", () => entity.url()); }); + describe("match", () => { + const handlers = { + // Return the address so we know it was actually called on the entity, + // and a hardcoded string so we know the right function was called. + repo: (x: R.Repo) => [x.address(), "REPO"], + issue: (x: R.Issue) => [x.address(), "ISSUE"], + pull: (x: R.Pull) => [x.address(), "PULL"], + review: (x: R.Review) => [x.address(), "REVIEW"], + comment: (x: R.Comment) => [x.address(), "COMMENT"], + userlike: (x: R.Userlike) => [x.address(), "USERLIKE"], + }; + + const instances = [repo, issue, pull, review, comment, userlike]; + for (const instance of instances) { + const [actualAddress, functionType] = R.match(handlers, instance); + expect(actualAddress.type).toEqual(functionType); + } + }); + describe("comment parent differentiation", () => { function hasCorrectParent(name, parent) { it(name, () => {