From 14025032ae4eda001f1ff613b3ae027461d59eb9 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Tue, 8 Apr 2025 12:53:27 -0400 Subject: [PATCH 01/16] overhaul contribution diff worker --- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 80 ++++++++++--------- src/Share/Metrics.hs | 28 +++++-- src/Share/Postgres/Notifications.hs | 2 +- 3 files changed, 63 insertions(+), 47 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 1dd795f8..cd94afe8 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -16,59 +16,63 @@ import Share.Metrics qualified as Metrics import Share.NamespaceDiffs (NamespaceDiffError (MissingEntityError)) import Share.Postgres qualified as PG import Share.Postgres.Contributions.Queries qualified as ContributionsQ +import Share.Postgres.IDs (CausalId) import Share.Postgres.Notifications qualified as Notif import Share.Postgres.Queries qualified as Q import Share.Prelude +import Share.Project (Project) import Share.Utils.Logging qualified as Logging import Share.Web.Authorization qualified as AuthZ import Share.Web.Errors (EntityMissing (..), ErrorID (..)) import Share.Web.Share.Diffs.Impl qualified as Diffs --- | Check every 10 minutes if we haven't heard on the notifications channel. +-- | Check every 30 seconds if we haven't heard on the notifications channel. -- Just in case we missed a notification. maxPollingIntervalSeconds :: Int -maxPollingIntervalSeconds = 10 * 60 +maxPollingIntervalSeconds = 30 worker :: Ki.Scope -> Background () worker scope = do authZReceipt <- AuthZ.backgroundJobAuthZ newWorker scope "diffs:contributions" $ forever do Notif.waitOnChannel Notif.ContributionDiffChannel (maxPollingIntervalSeconds * 1000000) - processDiffs authZReceipt >>= \case - Left (contributionId, e) -> - withTag "contribution-id" (IDs.toText contributionId) $ do - reportError e - Right _ -> pure () + processDiffs authZReceipt -processDiffs :: AuthZ.AuthZReceipt -> Background (Either (ContributionId, NamespaceDiffError) ()) -processDiffs authZReceipt = Metrics.recordContributionDiffDuration . runExceptT $ do - mayContributionId <- PG.runTransaction DQ.claimContributionToDiff - for_ mayContributionId (diffContribution authZReceipt) - case mayContributionId of - Just contributionId -> do - Logging.textLog ("Recomputed contribution diff: " <> tShow contributionId) - & Logging.withTag ("contribution-id", tShow contributionId) - & Logging.withSeverity Logging.Info - & Logging.logMsg - -- Keep processing releases until we run out of them. - either throwError pure =<< lift (processDiffs authZReceipt) - Nothing -> pure () +-- Process diffs until we run out of them. We claim a diff in a transaction, commit it, then proceed to compute the +-- diff. There's therefore a chance we claim a diff and fail to compute it (due to e.g. server restart). The current +-- solution to these "at most once" semantics is to simply re-enqueue a diff job if necessary; e.g. in the view diff +-- endpoint handler. +processDiffs :: AuthZ.AuthZReceipt -> Background () +processDiffs authZReceipt = do + let loop :: Background () + loop = do + whenJustM (PG.runTransaction DQ.claimContributionToDiff) \contributionId -> do + withTag "contribution-id" (IDs.toText contributionId) do + Metrics.recordContributionDiffDuration (diffContribution authZReceipt contributionId) >>= \case + Right () -> + Logging.textLog "Computed contribution diff" + & Logging.withSeverity Logging.Info + & Logging.logMsg + Left err -> reportError err + loop + loop -diffContribution :: AuthZ.AuthZReceipt -> ContributionId -> ExceptT (ContributionId, NamespaceDiffError) Background () -diffContribution authZReceipt contributionId = withExceptT (contributionId,) . mapExceptT (withTag "contribution-id" (IDs.toText contributionId)) $ do - ( bestCommonAncestorCausalId, - project, - newBranch@Branch {causal = newBranchCausalId}, - oldBranch@Branch {causal = oldBranchCausalId} - ) <- ExceptT $ PG.tryRunTransaction $ do - Contribution {bestCommonAncestorCausalId, sourceBranchId = newBranchId, targetBranchId = oldBranchId, projectId} <- ContributionsQ.contributionById contributionId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "contribution:missing") "Contribution not found") - project <- Q.projectById projectId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "project:missing") "Project not found") - newBranch <- Q.branchById newBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Source branch not found") - oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Target branch not found") - pure (bestCommonAncestorCausalId, project, newBranch, oldBranch) - let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch - let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch - -- This method saves the diff so it'll be there when we need it, so we don't need to do anything with it. - _ <- - Diffs.diffCausals authZReceipt (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) bestCommonAncestorCausalId - pure () +diffContribution :: AuthZ.AuthZReceipt -> ContributionId -> Background (Either NamespaceDiffError ()) +diffContribution authZReceipt contributionId = do + runExceptT do + (bestCommonAncestorCausalId, project, newBranch, oldBranch) <- ExceptT (PG.tryRunTransaction getContributionInfo) + let Branch {causal = oldBranchCausalId} = oldBranch + let Branch {causal = newBranchCausalId} = newBranch + let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch + let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch + _ <- Diffs.diffCausals authZReceipt (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) bestCommonAncestorCausalId + pure () + where + getContributionInfo :: PG.Transaction NamespaceDiffError (Maybe CausalId, Project, Branch CausalId, Branch CausalId) + getContributionInfo = do + Contribution {bestCommonAncestorCausalId, sourceBranchId = newBranchId, targetBranchId = oldBranchId, projectId} <- + ContributionsQ.contributionById contributionId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "contribution:missing") "Contribution not found") + project <- Q.projectById projectId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "project:missing") "Project not found") + newBranch <- Q.branchById newBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Source branch not found") + oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Target branch not found") + pure (bestCommonAncestorCausalId, project, newBranch, oldBranch) diff --git a/src/Share/Metrics.hs b/src/Share/Metrics.hs index a1d70561..26ca013a 100644 --- a/src/Share/Metrics.hs +++ b/src/Share/Metrics.hs @@ -14,6 +14,7 @@ module Share.Metrics ) where +import Data.Either.Combinators (whenRight) import Data.Ratio ((%)) import Data.Set qualified as Set import Data.Text qualified as Text @@ -413,15 +414,26 @@ contributionDiffDurationSeconds = timeActionIntoHistogram :: (Prom.Label l, MonadUnliftIO m) => (Prom.Vector l Prom.Histogram) -> l -> m c -> m c timeActionIntoHistogram histogram l m = do - UnliftIO.bracket start end \_ -> m - where - start = UnliftIO.liftIO $ Clock.getTime Monotonic - end startTime = UnliftIO.liftIO $ do - end <- Clock.getTime Monotonic + startTime <- liftIO $ Clock.getTime Monotonic + m `UnliftIO.finally` do + liftIO do + endTime <- Clock.getTime Monotonic let latency :: Double - latency = fromRational (toNanoSecs (end `diffTimeSpec` startTime) % 1000000000) + latency = fromRational (toNanoSecs (endTime `diffTimeSpec` startTime) % 1000000000) Prom.withLabel histogram l (flip Prom.observe latency) +-- | Like 'timeActionIntoHistogram', but only bothers to time actions that return 'Right' (indicating success). +timeRightActionIntoHistogram :: (Prom.Label l, MonadIO m) => (Prom.Vector l Prom.Histogram) -> l -> m (Either err c) -> m (Either err c) +timeRightActionIntoHistogram histogram l m = do + startTime <- liftIO $ Clock.getTime Monotonic + result <- m + whenRight result \_ -> liftIO do + endTime <- Clock.getTime Monotonic + let latency :: Double + latency = fromRational (toNanoSecs (endTime `diffTimeSpec` startTime) % 1000000000) + Prom.withLabel histogram l (flip Prom.observe latency) + pure result + -- | Record the duration of a background import. recordBackgroundImportDuration :: (MonadUnliftIO m) => m r -> m r recordBackgroundImportDuration = timeActionIntoHistogram backgroundImportDurationSeconds (deployment, service) @@ -430,5 +442,5 @@ recordBackgroundImportDuration = timeActionIntoHistogram backgroundImportDuratio recordDefinitionSearchIndexDuration :: (MonadUnliftIO m) => m r -> m r recordDefinitionSearchIndexDuration = timeActionIntoHistogram definitionSearchIndexDurationSeconds (deployment, service) -recordContributionDiffDuration :: (MonadUnliftIO m) => m r -> m r -recordContributionDiffDuration = timeActionIntoHistogram contributionDiffDurationSeconds (deployment, service) +recordContributionDiffDuration :: (MonadIO m) => m (Either err r) -> m (Either err r) +recordContributionDiffDuration = timeRightActionIntoHistogram contributionDiffDurationSeconds (deployment, service) diff --git a/src/Share/Postgres/Notifications.hs b/src/Share/Postgres/Notifications.hs index 3c93e335..30a2e619 100644 --- a/src/Share/Postgres/Notifications.hs +++ b/src/Share/Postgres/Notifications.hs @@ -39,7 +39,7 @@ notifs = unsafePerformIO $ STM.newTVarIO mempty initialize :: Ki.Scope -> -- The scope of the server Background () -initialize scope = void $ Ki.fork scope $ forever do +initialize scope = Ki.fork_ scope $ forever do result <- UnliftIO.try $ do PG.runSession $ do for_ [minBound .. maxBound] \kind -> do From 35c8ccfc31bb875114100ade422573b2f060de17 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Wed, 9 Apr 2025 14:38:38 -0400 Subject: [PATCH 02/16] generalize CodebaseRuntime --- src/Share/Backend.hs | 3 +- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 4 +- src/Share/BackgroundJobs/Diffs/Queries.hs | 36 ++--- src/Share/Codebase.hs | 108 ++++++++------ src/Share/Codebase/Types.hs | 6 +- src/Share/Postgres.hs | 1 + src/Share/Web/Share/Contributions/Impl.hs | 36 ++++- src/Share/Web/Share/Diffs/Impl.hs | 141 +++++++++--------- src/Share/Web/Share/Projects/Impl.hs | 22 ++- src/Unison/Server/Share/Definitions.hs | 8 +- src/Unison/Server/Share/NamespaceDetails.hs | 2 +- src/Unison/Server/Share/RenderDoc.hs | 2 +- 12 files changed, 216 insertions(+), 153 deletions(-) diff --git a/src/Share/Backend.hs b/src/Share/Backend.hs index 86d9712d..274b5f4b 100644 --- a/src/Share/Backend.hs +++ b/src/Share/Backend.hs @@ -231,7 +231,7 @@ displayType = \case pure (UserObject decl) evalDocRef :: - Codebase.CodebaseRuntime -> + Codebase.CodebaseRuntime IO -> V2.TermReference -> Codebase.CodebaseM e (Doc.EvaluatedDoc Symbol) evalDocRef (CodebaseRuntime {codeLookup, cachedEvalResult, unisonRuntime}) termRef = do @@ -245,6 +245,7 @@ evalDocRef (CodebaseRuntime {codeLookup, cachedEvalResult, unisonRuntime}) termR typeOf :: Referent.Referent -> Codebase.CodebaseM e (Maybe (V1.Type Symbol ())) typeOf termRef = fmap void <$> Codebase.loadTypeOfReferent (Cv.referent1to2 termRef) + eval :: V1.Term Symbol a -> Codebase.CodebaseM e (Maybe (V1.Term Symbol ())) eval (Term.amap (const mempty) -> tm) = do -- We use an empty ppe for evalutation, it's only used for adding additional context to errors. diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index cd94afe8..557688cc 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -65,7 +65,9 @@ diffContribution authZReceipt contributionId = do let Branch {causal = newBranchCausalId} = newBranch let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch - _ <- Diffs.diffCausals authZReceipt (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) bestCommonAncestorCausalId + oldRuntime <- lift (Codebase.codebaseRuntime oldCodebase) + newRuntime <- lift (Codebase.codebaseRuntime newCodebase) + _ <- Diffs.diffCausals authZReceipt (oldCodebase, oldRuntime, oldBranchCausalId) (newCodebase, newRuntime, newBranchCausalId) bestCommonAncestorCausalId pure () where getContributionInfo :: PG.Transaction NamespaceDiffError (Maybe CausalId, Project, Branch CausalId, Branch CausalId) diff --git a/src/Share/BackgroundJobs/Diffs/Queries.hs b/src/Share/BackgroundJobs/Diffs/Queries.hs index 02105741..a8cace3e 100644 --- a/src/Share/BackgroundJobs/Diffs/Queries.hs +++ b/src/Share/BackgroundJobs/Diffs/Queries.hs @@ -14,12 +14,12 @@ submitContributionsToBeDiffed :: (QueryM m) => Set ContributionId -> m () submitContributionsToBeDiffed contributions = do execute_ [sql| - WITH new_contributions(contribution_id) AS ( - SELECT * FROM ^{singleColumnTable (toList contributions)} - ) - INSERT INTO contribution_diff_queue (contribution_id) - SELECT nc.contribution_id FROM new_contributions nc - ON CONFLICT DO NOTHING + WITH new_contributions(contribution_id) AS ( + SELECT * FROM ^{singleColumnTable (toList contributions)} + ) + INSERT INTO contribution_diff_queue (contribution_id) + SELECT nc.contribution_id FROM new_contributions nc + ON CONFLICT DO NOTHING |] Notif.notifyChannel Notif.ContributionDiffChannel @@ -28,16 +28,16 @@ claimContributionToDiff :: Transaction e (Maybe ContributionId) claimContributionToDiff = do query1Col [sql| - WITH chosen_contribution(contribution_id) AS ( - SELECT q.contribution_id - FROM contribution_diff_queue q - ORDER BY q.created_at ASC - LIMIT 1 - -- Skip any that are being synced by other workers. - FOR UPDATE SKIP LOCKED - ) - DELETE FROM contribution_diff_queue - USING chosen_contribution - WHERE contribution_diff_queue.contribution_id = chosen_contribution.contribution_id - RETURNING chosen_contribution.contribution_id + WITH chosen_contribution(contribution_id) AS ( + SELECT q.contribution_id + FROM contribution_diff_queue q + ORDER BY q.created_at ASC + LIMIT 1 + -- Skip any that are being synced by other workers. + FOR UPDATE SKIP LOCKED + ) + DELETE FROM contribution_diff_queue + USING chosen_contribution + WHERE contribution_diff_queue.contribution_id = chosen_contribution.contribution_id + RETURNING chosen_contribution.contribution_id |] diff --git a/src/Share/Codebase.hs b/src/Share/Codebase.hs index ad33ab6f..71fc6391 100644 --- a/src/Share/Codebase.hs +++ b/src/Share/Codebase.hs @@ -17,6 +17,8 @@ module Share.Codebase CodebaseRuntime (..), codebaseEnv, codebaseRuntime, + codebaseRuntime', + badAskUnliftCodebaseRuntime, codebaseForProjectBranch, codebaseLocationForUserCodebase, codebaseLocationForProjectBranchCodebase, @@ -70,7 +72,9 @@ module Share.Codebase ) where +import Control.Concurrent.STM (TVar, atomically, modifyTVar', readTVarIO) import Control.Lens +import Control.Monad.Morph (hoist) import Data.ByteString.Lazy.Char8 qualified as BL import Data.Map qualified as Map import Data.Set qualified as Set @@ -110,6 +114,7 @@ import U.Codebase.Referent qualified as V2 import Unison.Builtin qualified as Builtin import Unison.Builtin qualified as Builtins import Unison.Codebase.CodeLookup qualified as CL +import Unison.Codebase.Runtime (Runtime) import Unison.Codebase.SqliteCodebase.Conversions qualified as Cv import Unison.ConstructorType qualified as CT import Unison.DataDeclaration qualified as DD @@ -174,14 +179,35 @@ codebaseEnv !_authZReceipt codebaseLoc = do -- | Construct a Runtime linked to a specific codebase. -- Don't use the runtime for one codebase with another codebase. -codebaseRuntime :: (MonadReader (Env.Env x) m, MonadUnliftIO m) => CodebaseEnv -> m CodebaseRuntime -codebaseRuntime CodebaseEnv {codebaseOwner} = do +codebaseRuntime :: (MonadReader (Env.Env x) m, MonadUnliftIO m) => CodebaseEnv -> m (CodebaseRuntime IO) +codebaseRuntime codebase = do unisonRuntime <- asks Env.sandboxedRuntime - codeLookup <- codeLookupForUser codebaseOwner - toIO <- UnliftIO.askRunInIO - let codebaseRt = CodebaseRuntime {codeLookup, cachedEvalResult, unisonRuntime} - cachedEvalResult r = (fmap . fmap) Term.unannotate . toIO . PG.runTransaction . loadCachedEvalResult codebaseOwner $ r - pure codebaseRt + cacheVar <- UnliftIO.newTVarIO (CodeLookupCache mempty mempty) + unlift <- badAskUnliftCodebaseRuntime + pure (unlift (codebaseRuntime' unisonRuntime cacheVar codebase)) + +-- | Ideally, we'd use this – a runtime with lookup actions in transaction, not IO. But that will require refactoring to +-- the runtime interface in ucm, so we can't use it for now. That's bad: we end up unsafely running separate +-- transactions for inner calls to 'codeLookup' / 'cachedEvalResult', which can lead to deadlock due to a starved +-- connection pool. +codebaseRuntime' :: Runtime Symbol -> TVar CodeLookupCache -> CodebaseEnv -> CodebaseRuntime (PG.Transaction e) +codebaseRuntime' unisonRuntime cacheVar CodebaseEnv {codebaseOwner} = + CodebaseRuntime + { codeLookup = codeLookupForUser cacheVar codebaseOwner, + cachedEvalResult = (fmap . fmap) Term.unannotate . loadCachedEvalResult codebaseOwner, + unisonRuntime + } + +badAskUnliftCodebaseRuntime :: + (MonadReader (Env.Env x) m, MonadUnliftIO m) => + m (CodebaseRuntime (PG.Transaction Void) -> CodebaseRuntime IO) +badAskUnliftCodebaseRuntime = do + UnliftIO.UnliftIO toIO <- askUnliftIO + pure \rt@CodebaseRuntime {codeLookup, cachedEvalResult} -> + rt + { codeLookup = hoist (toIO . PG.runTransaction) codeLookup, + cachedEvalResult = toIO . PG.runTransaction . cachedEvalResult + } runCodebaseTransaction :: (MonadReader (Env.Env x) m, MonadIO m) => CodebaseEnv -> CodebaseM Void a -> m a runCodebaseTransaction codebaseEnv m = do @@ -376,43 +402,41 @@ data CodeLookupCache = CodeLookupCache typeCache :: Map Reference.Id (V1.Decl Symbol Ann) } -codeLookupForUser :: (MonadUnliftIO m, MonadReader (Env.Env ctx) m) => UserId -> m (CL.CodeLookup Symbol IO Ann) -codeLookupForUser codebaseOwner = do - -- A simple append-only cache that lives for the duration of the request. - cacheVar <- UnliftIO.newTVarIO (CodeLookupCache mempty mempty) - unlift <- askUnliftIO - let getTermAndType :: Reference.Id -> IO (Maybe (V1.Term Symbol Ann, V1.Type Symbol Ann)) - getTermAndType r = do - let UnliftIO.UnliftIO toIO = unlift - CodeLookupCache {termCache} <- UnliftIO.atomically $ UnliftIO.readTVar cacheVar - case Map.lookup r termCache of - Just termAndType -> pure (Just termAndType) - Nothing -> do - mayTermAndType <- toIO . PG.runTransaction $ loadTermForCodeLookup codebaseOwner r - case mayTermAndType of - Just termAndType -> do - UnliftIO.atomically $ UnliftIO.modifyTVar cacheVar $ \CodeLookupCache {termCache, ..} -> +codeLookupForUser :: TVar CodeLookupCache -> UserId -> CL.CodeLookup Symbol (PG.Transaction e) Ann +codeLookupForUser cacheVar codebaseOwner = do + CL.CodeLookup (fmap (fmap fst) . getTermAndType) (fmap (fmap snd) . getTermAndType) getTypeDecl + <> Builtin.codeLookup + <> IOSource.codeLookupM + where + getTermAndType :: + Reference.Id -> + PG.Transaction e (Maybe (V1.Term Symbol Ann, V1.Type Symbol Ann)) + getTermAndType r = do + CodeLookupCache {termCache} <- PG.transactionUnsafeIO (readTVarIO cacheVar) + case Map.lookup r termCache of + Just termAndType -> pure (Just termAndType) + Nothing -> do + maybeTermAndType <- loadTermForCodeLookup codebaseOwner r + whenJust maybeTermAndType \termAndType -> do + PG.transactionUnsafeIO do + atomically do + modifyTVar' cacheVar \CodeLookupCache {termCache, ..} -> CodeLookupCache {termCache = Map.insert r termAndType termCache, ..} - pure (Just termAndType) - Nothing -> pure Nothing - - let getTypeDecl r = do - let UnliftIO.UnliftIO toIO = unlift - CodeLookupCache {typeCache} <- UnliftIO.atomically $ UnliftIO.readTVar cacheVar - case Map.lookup r typeCache of - Just typ -> pure (Just typ) - Nothing -> do - mayTypeDecl <- toIO . PG.runTransaction $ loadTypeDeclarationForCodeLookup codebaseOwner r - case mayTypeDecl of - Just typ -> do - UnliftIO.atomically $ UnliftIO.modifyTVar cacheVar $ \CodeLookupCache {typeCache, ..} -> + pure maybeTermAndType + + getTypeDecl :: Reference.Id -> PG.Transaction e (Maybe (V1.Decl Symbol Ann)) + getTypeDecl r = do + CodeLookupCache {typeCache} <- PG.transactionUnsafeIO (readTVarIO cacheVar) + case Map.lookup r typeCache of + Just typ -> pure (Just typ) + Nothing -> do + maybeType <- loadTypeDeclarationForCodeLookup codebaseOwner r + whenJust maybeType \typ -> + PG.transactionUnsafeIO do + atomically do + modifyTVar' cacheVar \CodeLookupCache {typeCache, ..} -> CodeLookupCache {typeCache = Map.insert r typ typeCache, ..} - pure (Just typ) - Nothing -> pure Nothing - pure $ - CL.CodeLookup (\r -> fmap fst <$> getTermAndType r) (\r -> fmap snd <$> getTermAndType r) getTypeDecl - <> Builtin.codeLookup - <> IOSource.codeLookupM + pure maybeType -- | Look up the result of evaluating a term if we have it cached. -- diff --git a/src/Share/Codebase/Types.hs b/src/Share/Codebase/Types.hs index 791dacb7..ecddfd8e 100644 --- a/src/Share/Codebase/Types.hs +++ b/src/Share/Codebase/Types.hs @@ -29,10 +29,10 @@ data CodebaseEnv = CodebaseEnv { codebaseOwner :: UserId } -data CodebaseRuntime = CodebaseRuntime - { codeLookup :: CL.CodeLookup Symbol IO Ann, +data CodebaseRuntime m = CodebaseRuntime + { codeLookup :: CL.CodeLookup Symbol m Ann, -- Function to look up cached evaluation results for the runtime. - cachedEvalResult :: Reference.Id -> IO (Maybe (Rt.Term Symbol)), + cachedEvalResult :: Reference.Id -> m (Maybe (Rt.Term Symbol)), unisonRuntime :: Rt.Runtime Symbol } diff --git a/src/Share/Postgres.hs b/src/Share/Postgres.hs index 3f691355..ab038dff 100644 --- a/src/Share/Postgres.hs +++ b/src/Share/Postgres.hs @@ -35,6 +35,7 @@ module Share.Postgres catchTransaction, unliftTransaction, runTransactionOrRespondError, + transaction, runSession, tryRunSession, runSessionOrRespondError, diff --git a/src/Share/Web/Share/Contributions/Impl.hs b/src/Share/Web/Share/Contributions/Impl.hs index 04ac72b7..d5abd629 100644 --- a/src/Share/Web/Share/Contributions/Impl.hs +++ b/src/Share/Web/Share/Contributions/Impl.hs @@ -280,7 +280,14 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr let cacheKeys = [IDs.toText contributionId, IDs.toText newPBSH, IDs.toText oldPBSH, Caching.causalIdCacheKey newBranchCausalId, Caching.causalIdCacheKey oldBranchCausalId] Caching.cachedResponse authZReceipt "contribution-diff" cacheKeys do - namespaceDiff <- respondExceptT (Diffs.diffCausals authZReceipt (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) bestCommonAncestorCausalId) + oldRuntime <- Codebase.codebaseRuntime oldCodebase + newRuntime <- Codebase.codebaseRuntime newCodebase + namespaceDiff <- respondExceptT do + Diffs.diffCausals + authZReceipt + (oldCodebase, oldRuntime, oldBranchCausalId) + (newCodebase, newRuntime, newBranchCausalId) + bestCommonAncestorCausalId (newBranchCausalHash, oldBranchCausalHash) <- PG.runTransaction do newBranchCausalHash <- CausalQ.expectCausalHashesByIdsOf id newBranchCausalId oldBranchCausalHash <- CausalQ.expectCausalHashesByIdsOf id oldBranchCausalId @@ -327,11 +334,21 @@ contributionDiffTermsEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHand let oldCausalId = fromMaybe oldBranchCausalId bestCommonAncestorCausalId let cacheKeys = [IDs.toText contributionId, IDs.toText newPBSH, IDs.toText oldPBSH, Caching.causalIdCacheKey newBranchCausalId, Caching.causalIdCacheKey oldCausalId, Name.toText oldTermName, Name.toText newTermName] Caching.cachedResponse authZReceipt "contribution-diff-terms" cacheKeys do - (oldBranchHashId, newBranchHashId) <- PG.runTransaction $ CausalQ.expectNamespaceIdsByCausalIdsOf both (oldCausalId, newBranchCausalId) - termDiff <- - respondExceptT (Diffs.diffTerms authZReceipt (oldCodebase, oldBranchHashId, oldTermName) (newCodebase, newBranchHashId, newTermName)) + oldRuntime <- Codebase.codebaseRuntime oldCodebase + newRuntime <- Codebase.codebaseRuntime newCodebase + termDiff <- do + result <- + PG.tryRunTransaction do + (oldBranchHashId, newBranchHashId) <- CausalQ.expectNamespaceIdsByCausalIdsOf both (oldCausalId, newBranchCausalId) + Diffs.diffTerms + authZReceipt + (oldCodebase, oldRuntime, oldBranchHashId, oldTermName) + (newCodebase, newRuntime, newBranchHashId, newTermName) + case result of + Left err -> respondError err -- Not exactly a "term not found" - one or both term names is a constructor - but probably ok for now - `whenNothingM` respondError (EntityMissing (ErrorID "term:missing") "Term not found") + Right Nothing -> respondError (EntityMissing (ErrorID "term:missing") "Term not found") + Right (Just diff) -> pure diff pure ShareTermDiffResponse { project = projectShorthand, @@ -375,8 +392,13 @@ contributionDiffTypesEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHand let oldCausalId = fromMaybe oldBranchCausalId bestCommonAncestorCausalId let cacheKeys = [IDs.toText contributionId, IDs.toText newPBSH, IDs.toText oldPBSH, Caching.causalIdCacheKey newBranchCausalId, Caching.causalIdCacheKey oldCausalId, Name.toText oldTypeName, Name.toText newTypeName] Caching.cachedResponse authZReceipt "contribution-diff-types" cacheKeys do - (oldBranchHashId, newBranchHashId) <- PG.runTransaction $ CausalQ.expectNamespaceIdsByCausalIdsOf both (oldCausalId, newBranchCausalId) - typeDiff <- respondExceptT (Diffs.diffTypes authZReceipt (oldCodebase, oldBranchHashId, oldTypeName) (newCodebase, newBranchHashId, newTypeName)) + oldRuntime <- Codebase.codebaseRuntime oldCodebase + newRuntime <- Codebase.codebaseRuntime newCodebase + typeDiff <- + (either respondError pure =<<) do + PG.tryRunTransaction do + (oldBranchHashId, newBranchHashId) <- CausalQ.expectNamespaceIdsByCausalIdsOf both (oldCausalId, newBranchCausalId) + Diffs.diffTypes authZReceipt (oldCodebase, oldRuntime, oldBranchHashId, oldTypeName) (newCodebase, newRuntime, newBranchHashId, newTypeName) pure $ ShareTypeDiffResponse { project = projectShorthand, diff --git a/src/Share/Web/Share/Diffs/Impl.hs b/src/Share/Web/Share/Diffs/Impl.hs index e2908b3f..35d7b8b4 100644 --- a/src/Share/Web/Share/Diffs/Impl.hs +++ b/src/Share/Web/Share/Diffs/Impl.hs @@ -55,8 +55,8 @@ import UnliftIO qualified diffCausals :: AuthZReceipt -> - (Codebase.CodebaseEnv, CausalId) -> - (Codebase.CodebaseEnv, CausalId) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> Maybe CausalId -> ExceptT NamespaceDiffs.NamespaceDiffError @@ -72,7 +72,7 @@ diffCausals :: BranchHash ) ) -diffCausals !authZReceipt (oldCodebase, oldCausalId) (newCodebase, newCausalId) maybeLcaCausalId = do +diffCausals !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do -- Ensure name lookups for the things we're diffing. -- We do this in separate transactions to ensure we can still make progress even if we need to build name lookups. let getBranch :: CausalId -> ExceptT NamespaceDiffs.NamespaceDiffError (AppM r) (BranchHashId, NameLookupReceipt) @@ -161,12 +161,14 @@ diffCausals !authZReceipt (oldCodebase, oldCausalId) (newCodebase, newCausalId) -- diff relative to, unless there isn't an LCA (unlikely), in which case we fall back on the other branch (we -- won't have anything classified as an "update" in this case so it doesn't really matter). diff1 <- - diff0 - & NamespaceDiffs.namespaceAndLibdepsDiffDefns_ - %%~ computeUpdatedDefinitionDiffs - authZReceipt - (oldCodebase, fromMaybe oldBranchHashId maybeLcaBranchHashId) - (newCodebase, newBranchHashId) + ExceptT do + PG.tryRunTransaction do + diff0 + & NamespaceDiffs.namespaceAndLibdepsDiffDefns_ + %%~ computeUpdatedDefinitionDiffs + authZReceipt + (oldCodebase, oldRuntime, fromMaybe oldBranchHashId maybeLcaBranchHashId) + (newCodebase, newRuntime, newBranchHashId) let encoded = Aeson.encode (RenderedNamespaceAndLibdepsDiff diff1) PG.runTransaction $ ContributionQ.savePrecomputedNamespaceDiff @@ -176,28 +178,27 @@ diffCausals !authZReceipt (oldCodebase, oldCausalId) (newCodebase, newCausalId) pure $ PreEncoded encoded computeUpdatedDefinitionDiffs :: - forall a b r. + forall a b. (Ord a, Ord b) => AuthZReceipt -> - (Codebase.CodebaseEnv, BranchHashId) -> - (Codebase.CodebaseEnv, BranchHashId) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId) -> GNamespaceTreeDiff NameSegment a b Name Name Name Name -> - ExceptT + PG.Transaction NamespaceDiffError - (AppM r) (NamespaceDiffs.NamespaceTreeDiff a b TermDefinition TypeDefinition TermDefinitionDiff TypeDefinitionDiff) -computeUpdatedDefinitionDiffs !authZReceipt (fromCodebase, fromBHId) (toCodebase, toBHId) diff0 = do +computeUpdatedDefinitionDiffs !authZReceipt (fromCodebase, fromRuntime, fromBHId) (toCodebase, toRuntime, toBHId) diff0 = do diff1 <- NamespaceDiffs.witherNamespaceTreeDiffTermDiffs - (\name -> diffTerms authZReceipt (fromCodebase, fromBHId, name) (toCodebase, toBHId, name)) + (\name -> diffTerms authZReceipt (fromCodebase, fromRuntime, fromBHId, name) (toCodebase, toRuntime, toBHId, name)) diff0 diff2 <- NamespaceDiffs.witherNamespaceTreeTermDiffKinds - (throwAwayConstructorDiffs . renderDiffKind (ExceptT . fmap sequence . getTermDefinition)) + (fmap throwAwayConstructorDiffs . renderDiffKind getTermDefinition) diff1 diff3 <- NamespaceDiffs.namespaceTreeDiffTypeDiffs_ - (\name -> diffTypes authZReceipt (fromCodebase, fromBHId, name) (toCodebase, toBHId, name)) + (\name -> diffTypes authZReceipt (fromCodebase, fromRuntime, fromBHId, name) (toCodebase, toRuntime, toBHId, name)) diff2 diff4 <- NamespaceDiffs.namespaceTreeTypeDiffKinds_ @@ -208,44 +209,45 @@ computeUpdatedDefinitionDiffs !authZReceipt (fromCodebase, fromBHId) (toCodebase notFound name t = MissingEntityError $ EntityMissing (ErrorID "definition-not-found") (t <> ": Definition not found: " <> Name.toText name) renderDiffKind :: - forall diff m r x. - (Monad m) => - ((Codebase.CodebaseEnv, BranchHashId, Name) -> m (Maybe x)) -> + forall diff r x. + ((Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> PG.Transaction NamespaceDiffError (Maybe x)) -> DefinitionDiffKind r Name diff -> - ExceptT NamespaceDiffError m (DefinitionDiffKind r x diff) + PG.Transaction NamespaceDiffError (DefinitionDiffKind r x diff) renderDiffKind getter = \case - Added r name -> Added r <$> (lift (getter (toCodebase, toBHId, name)) `whenNothingM` throwError (notFound name "Added")) - NewAlias r existingNames name -> NewAlias r existingNames <$> (lift (getter (toCodebase, toBHId, name)) `whenNothingM` throwError (notFound name "NewAlias")) - Removed r name -> Removed r <$> (lift (getter (fromCodebase, fromBHId, name)) `whenNothingM` throwError (notFound name "Removed")) + Added r name -> Added r <$> (getter (toCodebase, toRuntime, toBHId, name) `whenNothingM` throwError (notFound name "Added")) + NewAlias r existingNames name -> NewAlias r existingNames <$> (getter (toCodebase, toRuntime, toBHId, name) `whenNothingM` throwError (notFound name "NewAlias")) + Removed r name -> Removed r <$> (getter (fromCodebase, fromRuntime, fromBHId, name) `whenNothingM` throwError (notFound name "Removed")) Updated oldRef newRef diff -> pure $ Updated oldRef newRef diff Propagated oldRef newRef diff -> pure $ Propagated oldRef newRef diff - RenamedTo r names name -> RenamedTo r names <$> (lift (getter (fromCodebase, fromBHId, name)) `whenNothingM` throwError (notFound name "RenamedTo")) - RenamedFrom r names name -> RenamedFrom r names <$> (lift (getter (toCodebase, toBHId, name)) `whenNothingM` throwError (notFound name "RenamedFrom")) + RenamedTo r names name -> RenamedTo r names <$> (getter (fromCodebase, fromRuntime, fromBHId, name) `whenNothingM` throwError (notFound name "RenamedTo")) + RenamedFrom r names name -> RenamedFrom r names <$> (getter (toCodebase, toRuntime, toBHId, name) `whenNothingM` throwError (notFound name "RenamedFrom")) throwAwayConstructorDiffs :: - ExceptT - NamespaceDiffError - (ExceptT ConstructorReference (AppM r)) - (DefinitionDiffKind a TermDefinition TermDefinitionDiff) -> - ExceptT - NamespaceDiffError - (AppM r) - (Maybe (DefinitionDiffKind a TermDefinition TermDefinitionDiff)) - throwAwayConstructorDiffs m = - lift (runExceptT (runExceptT m)) >>= \case - Left _ref -> pure Nothing - Right (Left err) -> throwError err - Right (Right diff) -> pure (Just diff) + DefinitionDiffKind a (Either ConstructorReference TermDefinition) diff -> Maybe (DefinitionDiffKind a TermDefinition diff) + throwAwayConstructorDiffs = \case + Added ref (Right term) -> Just (Added ref term) + NewAlias ref names (Right term) -> Just (NewAlias ref names term) + Removed ref (Right term) -> Just (Removed ref term) + Updated old new diff -> Just (Updated old new diff) + Propagated old new diff -> Just (Propagated old new diff) + RenamedTo ref names (Right term) -> Just (RenamedTo ref names term) + RenamedFrom ref names (Right term) -> Just (RenamedFrom ref names term) + -- + Added _ (Left _) -> Nothing + NewAlias _ _ (Left _) -> Nothing + Removed _ (Left _) -> Nothing + RenamedFrom _ _ (Left _) -> Nothing + RenamedTo _ _ (Left _) -> Nothing diffTerms :: AuthZReceipt -> - (Codebase.CodebaseEnv, BranchHashId, Name) -> - (Codebase.CodebaseEnv, BranchHashId, Name) -> - ExceptT NamespaceDiffError (AppM r) (Maybe TermDefinitionDiff) -diffTerms !_authZReceipt old@(_, _, oldName) new@(_, _, newName) = do - let getOldTerm = lift (getTermDefinition old) `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "term-not-found") ("'From' term not found: " <> Name.toText oldName)) - let getNewTerm = lift (getTermDefinition new) `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "term-not-found") ("'To' term not found: " <> Name.toText newName)) - (getOldTerm `concurrentExceptT` getNewTerm) >>= \case + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> + PG.Transaction NamespaceDiffError (Maybe TermDefinitionDiff) +diffTerms !_authZReceipt old@(_, _, _, oldName) new@(_, _, _, newName) = do + oldTerm <- getTermDefinition old `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "term-not-found") ("'From' term not found: " <> Name.toText oldName)) + newTerm <- getTermDefinition new `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "term-not-found") ("'To' term not found: " <> Name.toText newName)) + case (oldTerm, newTerm) of (Right oldTerm, Right newTerm) -> do let termDiffDisplayObject = DefinitionDiff.diffDisplayObjects (termDefinition oldTerm) (termDefinition newTerm) pure (Just TermDefinitionDiff {left = oldTerm, right = newTerm, diff = termDiffDisplayObject}) @@ -253,14 +255,13 @@ diffTerms !_authZReceipt old@(_, _, oldName) new@(_, _, newName) = do -- Just dropping them from the diff for now _ -> pure Nothing -getTermDefinition :: (Codebase.CodebaseEnv, BranchHashId, Name) -> AppM r (Maybe (Either ConstructorReference TermDefinition)) -getTermDefinition (codebase, bhId, name) = do +getTermDefinition :: (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> PG.Transaction e (Maybe (Either ConstructorReference TermDefinition)) +getTermDefinition (codebase, rt, bhId, name) = do let perspective = mempty - (namesPerspective, Identity relocatedName) <- PG.runTransaction $ NameLookupOps.relocateToNameRoot perspective (Identity name) bhId - let ppedBuilder deps = (PPED.biasTo [name]) <$> lift (PPEPostgres.ppedForReferences namesPerspective deps) + (namesPerspective, Identity relocatedName) <- NameLookupOps.relocateToNameRoot perspective (Identity name) bhId + let ppedBuilder deps = PPED.biasTo [name] <$> PPEPostgres.ppedForReferences namesPerspective deps let nameSearch = PGNameSearch.nameSearchForPerspective namesPerspective - rt <- Codebase.codebaseRuntime codebase - Codebase.runCodebaseTransaction codebase do + Codebase.codebaseMToTransaction codebase do Definitions.termDefinitionByName ppedBuilder nameSearch renderWidth rt relocatedName where renderWidth :: Width @@ -268,28 +269,26 @@ getTermDefinition (codebase, bhId, name) = do diffTypes :: AuthZReceipt -> - (Codebase.CodebaseEnv, BranchHashId, Name) -> - (Codebase.CodebaseEnv, BranchHashId, Name) -> - ExceptT NamespaceDiffError (AppM r) TypeDefinitionDiff -diffTypes !_authZReceipt old@(_, _, oldTypeName) new@(_, _, newTypeName) = do - let getOldType = - lift (getTypeDefinition old) - `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "type-not-found") ("'From' Type not found: " <> Name.toText oldTypeName)) - let getNewType = - lift (getTypeDefinition new) - `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "type-not-found") ("'To' Type not found: " <> Name.toText newTypeName)) - (sourceType, newType) <- getOldType `concurrentExceptT` getNewType - let typeDiffDisplayObject = DefinitionDiff.diffDisplayObjects (typeDefinition sourceType) (typeDefinition newType) - pure $ TypeDefinitionDiff {left = sourceType, right = newType, diff = typeDiffDisplayObject} + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> + PG.Transaction NamespaceDiffError TypeDefinitionDiff +diffTypes !_authZReceipt old@(_, _, _, oldTypeName) new@(_, _, _, newTypeName) = do + oldType <- + getTypeDefinition old + `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "type-not-found") ("'From' Type not found: " <> Name.toText oldTypeName)) + newType <- + getTypeDefinition new + `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "type-not-found") ("'To' Type not found: " <> Name.toText newTypeName)) + let typeDiffDisplayObject = DefinitionDiff.diffDisplayObjects (typeDefinition oldType) (typeDefinition newType) + pure $ TypeDefinitionDiff {left = oldType, right = newType, diff = typeDiffDisplayObject} -getTypeDefinition :: (Codebase.CodebaseEnv, BranchHashId, Name) -> AppM r (Maybe TypeDefinition) -getTypeDefinition (codebase, bhId, name) = do +getTypeDefinition :: (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, BranchHashId, Name) -> PG.Transaction e (Maybe TypeDefinition) +getTypeDefinition (codebase, rt, bhId, name) = do let perspective = mempty - (namesPerspective, Identity relocatedName) <- PG.runTransaction $ NameLookupOps.relocateToNameRoot perspective (Identity name) bhId + (namesPerspective, Identity relocatedName) <- NameLookupOps.relocateToNameRoot perspective (Identity name) bhId let ppedBuilder deps = (PPED.biasTo [name]) <$> lift (PPEPostgres.ppedForReferences namesPerspective deps) let nameSearch = PGNameSearch.nameSearchForPerspective namesPerspective - rt <- Codebase.codebaseRuntime codebase - Codebase.runCodebaseTransaction codebase do + Codebase.codebaseMToTransaction codebase do Definitions.typeDefinitionByName ppedBuilder nameSearch renderWidth rt relocatedName where renderWidth :: Width diff --git a/src/Share/Web/Share/Projects/Impl.hs b/src/Share/Web/Share/Projects/Impl.hs index d75eac36..19293df7 100644 --- a/src/Share/Web/Share/Projects/Impl.hs +++ b/src/Share/Web/Share/Projects/Impl.hs @@ -166,7 +166,9 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project (oldCausalHash, newCausalHash) <- CausalQ.expectCausalHashesByIdsOf each (oldCausalId, newCausalId) maybeLcaCausalId <- CausalQ.bestCommonAncestor oldCausalId newCausalId pure (oldCausalHash, newCausalHash, maybeLcaCausalId) - namespaceDiff <- respondExceptT (Diffs.diffCausals authZReceipt (oldCodebase, oldCausalId) (newCodebase, newCausalId) maybeLcaCausalId) + oldRuntime <- Codebase.codebaseRuntime oldCodebase + newRuntime <- Codebase.codebaseRuntime newCodebase + namespaceDiff <- respondExceptT (Diffs.diffCausals authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId) pure ShareNamespaceDiffResponse { project = projectShortHand, @@ -199,10 +201,14 @@ projectDiffTermsEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle proje let cacheKeys = [IDs.toText projectId, IDs.toText oldShortHand, IDs.toText newShortHand, Caching.branchIdCacheKey oldBhId, Caching.branchIdCacheKey newBhId, Name.toText oldTermName, Name.toText newTermName] Caching.cachedResponse authZReceipt "project-diff-terms" cacheKeys do + oldRuntime <- Codebase.codebaseRuntime oldCodebase + newRuntime <- Codebase.codebaseRuntime newCodebase termDiff <- - respondExceptT (Diffs.diffTerms authZReceipt (oldCodebase, oldBhId, oldTermName) (newCodebase, newBhId, newTermName)) + PG.tryRunTransaction (Diffs.diffTerms authZReceipt (oldCodebase, oldRuntime, oldBhId, oldTermName) (newCodebase, newRuntime, newBhId, newTermName)) >>= \case + Left err -> respondError err -- Not exactly a "term not found" - one or both term names is a constructor - but probably ok for now - `whenNothingM` respondError (EntityMissing (ErrorID "term:missing") "Term not found") + Right Nothing -> respondError (EntityMissing (ErrorID "term:missing") "Term not found") + Right (Just diff) -> pure diff pure $ ShareTermDiffResponse { project = projectShortHand, @@ -236,7 +242,15 @@ projectDiffTypesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle proje let cacheKeys = [IDs.toText projectId, IDs.toText oldShortHand, IDs.toText newShortHand, Caching.branchIdCacheKey oldBhId, Caching.branchIdCacheKey newBhId, Name.toText oldTypeName, Name.toText newTypeName] Caching.cachedResponse authZReceipt "project-diff-types" cacheKeys do - typeDiff <- respondExceptT (Diffs.diffTypes authZReceipt (oldCodebase, oldBhId, oldTypeName) (newCodebase, newBhId, newTypeName)) + oldRuntime <- Codebase.codebaseRuntime oldCodebase + newRuntime <- Codebase.codebaseRuntime newCodebase + typeDiff <- + (either respondError pure =<<) do + PG.tryRunTransaction do + Diffs.diffTypes + authZReceipt + (oldCodebase, oldRuntime, oldBhId, oldTypeName) + (newCodebase, newRuntime, newBhId, newTypeName) pure $ ShareTypeDiffResponse { project = projectShortHand, diff --git a/src/Unison/Server/Share/Definitions.hs b/src/Unison/Server/Share/Definitions.hs index d51d671c..b0a547bf 100644 --- a/src/Unison/Server/Share/Definitions.hs +++ b/src/Unison/Server/Share/Definitions.hs @@ -77,7 +77,7 @@ definitionForHQName :: -- | Whether to suffixify bindings in the rendered syntax Suffixify -> -- | Runtime used to evaluate docs. This should be sandboxed if run on the server. - CodebaseRuntime -> + CodebaseRuntime IO -> -- | The name, hash, or both, of the definition to display. HQ.HashQualified Name -> Codebase.CodebaseM e DefinitionDisplayResults @@ -143,7 +143,7 @@ definitionForHQName perspective rootCausalId renderWidth suffixifyBindings rt pe renderDocRefs :: PPEDBuilder (Codebase.CodebaseM e) -> Width -> - CodebaseRuntime -> + CodebaseRuntime IO -> [TermReference] -> Codebase.CodebaseM e [(HashQualifiedName, UnisonHash, Doc.Doc)] renderDocRefs _ppedBuilder _width _rt [] = pure [] @@ -207,7 +207,7 @@ termDefinitionByName :: PPEDBuilder (Codebase.CodebaseM e) -> NameSearch (PG.Transaction e) -> Width -> - CodebaseRuntime -> + CodebaseRuntime IO -> Name -> Codebase.CodebaseM e (Maybe (Either ConstructorReference TermDefinition)) termDefinitionByName ppedBuilder nameSearch width rt name = runMaybeT do @@ -241,7 +241,7 @@ typeDefinitionByName :: PPEDBuilder (Codebase.CodebaseM e) -> NameSearch (PG.Transaction e) -> Width -> - CodebaseRuntime -> + CodebaseRuntime IO -> Name -> Codebase.CodebaseM e (Maybe TypeDefinition) typeDefinitionByName ppedBuilder nameSearch width rt name = runMaybeT $ do diff --git a/src/Unison/Server/Share/NamespaceDetails.hs b/src/Unison/Server/Share/NamespaceDetails.hs index 406bf197..bb1e1c1b 100644 --- a/src/Unison/Server/Share/NamespaceDetails.hs +++ b/src/Unison/Server/Share/NamespaceDetails.hs @@ -17,7 +17,7 @@ import Unison.Server.Types import Unison.Util.Pretty (Width) namespaceDetails :: - CodebaseRuntime -> + CodebaseRuntime IO -> Path.Path -> CausalId -> Maybe Width -> diff --git a/src/Unison/Server/Share/RenderDoc.hs b/src/Unison/Server/Share/RenderDoc.hs index 1246dac8..4df2fd45 100644 --- a/src/Unison/Server/Share/RenderDoc.hs +++ b/src/Unison/Server/Share/RenderDoc.hs @@ -37,7 +37,7 @@ import Unison.Util.Pretty (Width) -- Requires Name Lookups, currently only usable on Share. findAndRenderDoc :: Set NameSegment -> - CodebaseRuntime -> + CodebaseRuntime IO -> Path.Path -> CausalId -> Maybe Width -> From 275055d45f4d2e18733a115efe24fd3feaee73d6 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Wed, 9 Apr 2025 14:49:26 -0400 Subject: [PATCH 03/16] make diffCausals a single transaction --- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 2 +- src/Share/Web/Share/Contributions/Impl.hs | 14 +- src/Share/Web/Share/Diffs/Impl.hs | 184 ++++++++---------- src/Share/Web/Share/Projects/Impl.hs | 9 +- 4 files changed, 99 insertions(+), 110 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 557688cc..917bfce9 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -67,7 +67,7 @@ diffContribution authZReceipt contributionId = do let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch oldRuntime <- lift (Codebase.codebaseRuntime oldCodebase) newRuntime <- lift (Codebase.codebaseRuntime newCodebase) - _ <- Diffs.diffCausals authZReceipt (oldCodebase, oldRuntime, oldBranchCausalId) (newCodebase, newRuntime, newBranchCausalId) bestCommonAncestorCausalId + _ <- ExceptT (PG.tryRunTransaction (Diffs.diffCausals authZReceipt (oldCodebase, oldRuntime, oldBranchCausalId) (newCodebase, newRuntime, newBranchCausalId) bestCommonAncestorCausalId)) pure () where getContributionInfo :: PG.Transaction NamespaceDiffError (Maybe CausalId, Project, Branch CausalId, Branch CausalId) diff --git a/src/Share/Web/Share/Contributions/Impl.hs b/src/Share/Web/Share/Contributions/Impl.hs index d5abd629..f6c289b8 100644 --- a/src/Share/Web/Share/Contributions/Impl.hs +++ b/src/Share/Web/Share/Contributions/Impl.hs @@ -282,12 +282,14 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr Caching.cachedResponse authZReceipt "contribution-diff" cacheKeys do oldRuntime <- Codebase.codebaseRuntime oldCodebase newRuntime <- Codebase.codebaseRuntime newCodebase - namespaceDiff <- respondExceptT do - Diffs.diffCausals - authZReceipt - (oldCodebase, oldRuntime, oldBranchCausalId) - (newCodebase, newRuntime, newBranchCausalId) - bestCommonAncestorCausalId + namespaceDiff <- + (either respondError pure =<<) do + PG.tryRunTransaction do + Diffs.diffCausals + authZReceipt + (oldCodebase, oldRuntime, oldBranchCausalId) + (newCodebase, newRuntime, newBranchCausalId) + bestCommonAncestorCausalId (newBranchCausalHash, oldBranchCausalHash) <- PG.runTransaction do newBranchCausalHash <- CausalQ.expectCausalHashesByIdsOf id newBranchCausalId oldBranchCausalHash <- CausalQ.expectCausalHashesByIdsOf id oldBranchCausalId diff --git a/src/Share/Web/Share/Diffs/Impl.hs b/src/Share/Web/Share/Diffs/Impl.hs index 35d7b8b4..91c56950 100644 --- a/src/Share/Web/Share/Diffs/Impl.hs +++ b/src/Share/Web/Share/Diffs/Impl.hs @@ -8,7 +8,6 @@ where import Control.Comonad.Cofree qualified as Cofree import Control.Lens hiding ((.=)) import Control.Monad.Except -import Control.Monad.Trans.Except (except) import Data.Aeson (ToJSON (..), Value, (.=)) import Data.Aeson qualified as Aeson import Data.Aeson.Types (object) @@ -16,7 +15,6 @@ import Data.Foldable qualified as Foldable import Data.Map qualified as Map import Data.Text.Lazy qualified as TL import Data.Text.Lazy.Encoding qualified as TL -import Share.App (AppM) import Share.Codebase qualified as Codebase import Share.NamespaceDiffs (DefinitionDiff (..), DefinitionDiffKind (..), DiffAtPath (..), GNamespaceAndLibdepsDiff, GNamespaceTreeDiff, NamespaceAndLibdepsDiff, NamespaceDiffError (..), NamespaceTreeDiff) import Share.NamespaceDiffs qualified as NamespaceDiffs @@ -51,16 +49,14 @@ import Unison.Server.Types import Unison.ShortHash (ShortHash) import Unison.Syntax.Name qualified as Name import Unison.Util.Pretty (Width) -import UnliftIO qualified diffCausals :: AuthZReceipt -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> Maybe CausalId -> - ExceptT + PG.Transaction NamespaceDiffs.NamespaceDiffError - (AppM r) ( PreEncoded ( NamespaceDiffs.NamespaceAndLibdepsDiff (TermTag, ShortHash) @@ -74,16 +70,14 @@ diffCausals :: ) diffCausals !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do -- Ensure name lookups for the things we're diffing. - -- We do this in separate transactions to ensure we can still make progress even if we need to build name lookups. - let getBranch :: CausalId -> ExceptT NamespaceDiffs.NamespaceDiffError (AppM r) (BranchHashId, NameLookupReceipt) - getBranch causalId = - PG.runTransaction do - branchHashId <- CausalQ.expectNamespaceIdsByCausalIdsOf id causalId - nameLookupReceipt <- NLOps.ensureNameLookupForBranchId branchHashId - pure (branchHashId, nameLookupReceipt) - (((oldBranchHashId, oldBranchNLReceipt), (newBranchHashId, newBranchNLReceipt))) <- - getBranch oldCausalId `concurrentExceptT` getBranch newCausalId - PG.runTransaction (ContributionQ.getPrecomputedNamespaceDiff (oldCodebase, oldCausalId) (newCodebase, newCausalId)) >>= \case + let getBranch :: CausalId -> PG.Transaction NamespaceDiffs.NamespaceDiffError (BranchHashId, NameLookupReceipt) + getBranch causalId = do + branchHashId <- CausalQ.expectNamespaceIdsByCausalIdsOf id causalId + nameLookupReceipt <- NLOps.ensureNameLookupForBranchId branchHashId + pure (branchHashId, nameLookupReceipt) + (oldBranchHashId, oldBranchNLReceipt) <- getBranch oldCausalId + (newBranchHashId, newBranchNLReceipt) <- getBranch newCausalId + ContributionQ.getPrecomputedNamespaceDiff (oldCodebase, oldCausalId) (newCodebase, newCausalId) >>= \case Just diff -> pure $ PreEncoded $ TL.encodeUtf8 $ TL.fromStrict diff Nothing -> do (maybeLcaBranchHashId, maybeLcaBranchNLReceipt) <- @@ -92,89 +86,82 @@ diffCausals !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, n (lcaBranchHashId, lcaBranchNLReceipt) <- getBranch lcaCausalId pure (Just lcaBranchHashId, Just lcaBranchNLReceipt) Nothing -> pure (Nothing, Nothing) - diff0 <- - ExceptT do - PG.tryRunTransaction do - -- Do the initial 3-way namespace diff - diff :: - GNamespaceAndLibdepsDiff - NameSegment - Referent - TypeReference - Name - Name - Name - Name - BranchHashId <- - NamespaceDiffs.computeThreeWayNamespaceDiff - TwoWay {alice = oldCodebase, bob = newCodebase} - TwoOrThreeWay {alice = oldBranchHashId, bob = newBranchHashId, lca = maybeLcaBranchHashId} - TwoOrThreeWay {alice = oldBranchNLReceipt, bob = newBranchNLReceipt, lca = maybeLcaBranchNLReceipt} - -- Resolve the term referents to tag + hash - diff1 :: - GNamespaceAndLibdepsDiff - NameSegment - (TermTag, ShortHash) - TypeReference - Name - Name - Name - Name - BranchHashId <- - diff - & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferents_) - %%~ \refs -> do - termTags <- Codebase.termTagsByReferentsOf (\f -> traverse (f . referent1to2)) refs - pure $ zip termTags (refs <&> Referent.toShortHash) - -- Resolve the type references to tag + hash - diff2 :: - GNamespaceAndLibdepsDiff - NameSegment - (TermTag, ShortHash) - (TypeTag, ShortHash) - Name - Name - Name - Name - BranchHashId <- - diff1 - & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferences_) - %%~ \refs -> do - typeTags <- Codebase.typeTagsByReferencesOf traversed refs - pure $ zip typeTags (refs <&> V2Reference.toShortHash) - -- Resolve libdeps branch hash ids to branch hashes - diff3 :: - GNamespaceAndLibdepsDiff - NameSegment - (TermTag, ShortHash) - (TypeTag, ShortHash) - Name - Name - Name - Name - BranchHash <- - HashQ.expectNamespaceHashesByNamespaceHashIdsOf - (NamespaceDiffs.namespaceAndLibdepsDiffLibdeps_ . traversed . traversed) - diff2 - pure diff3 + -- Do the initial 3-way namespace diff + diff0 :: + GNamespaceAndLibdepsDiff + NameSegment + Referent + TypeReference + Name + Name + Name + Name + BranchHashId <- + NamespaceDiffs.computeThreeWayNamespaceDiff + TwoWay {alice = oldCodebase, bob = newCodebase} + TwoOrThreeWay {alice = oldBranchHashId, bob = newBranchHashId, lca = maybeLcaBranchHashId} + TwoOrThreeWay {alice = oldBranchNLReceipt, bob = newBranchNLReceipt, lca = maybeLcaBranchNLReceipt} + -- Resolve the term referents to tag + hash + diff1 :: + GNamespaceAndLibdepsDiff + NameSegment + (TermTag, ShortHash) + TypeReference + Name + Name + Name + Name + BranchHashId <- + diff0 + & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferents_) + %%~ \refs -> do + termTags <- Codebase.termTagsByReferentsOf (\f -> traverse (f . referent1to2)) refs + pure $ zip termTags (refs <&> Referent.toShortHash) + -- Resolve the type references to tag + hash + diff2 :: + GNamespaceAndLibdepsDiff + NameSegment + (TermTag, ShortHash) + (TypeTag, ShortHash) + Name + Name + Name + Name + BranchHashId <- + diff1 + & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferences_) + %%~ \refs -> do + typeTags <- Codebase.typeTagsByReferencesOf traversed refs + pure $ zip typeTags (refs <&> V2Reference.toShortHash) + -- Resolve libdeps branch hash ids to branch hashes + diff3 :: + GNamespaceAndLibdepsDiff + NameSegment + (TermTag, ShortHash) + (TypeTag, ShortHash) + Name + Name + Name + Name + BranchHash <- + HashQ.expectNamespaceHashesByNamespaceHashIdsOf + (NamespaceDiffs.namespaceAndLibdepsDiffLibdeps_ . traversed . traversed) + diff2 -- Resolve the actual term/type definitions. Use the LCA as the "old" (because that's what we're rendering the -- diff relative to, unless there isn't an LCA (unlikely), in which case we fall back on the other branch (we -- won't have anything classified as an "update" in this case so it doesn't really matter). - diff1 <- - ExceptT do - PG.tryRunTransaction do - diff0 - & NamespaceDiffs.namespaceAndLibdepsDiffDefns_ - %%~ computeUpdatedDefinitionDiffs - authZReceipt - (oldCodebase, oldRuntime, fromMaybe oldBranchHashId maybeLcaBranchHashId) - (newCodebase, newRuntime, newBranchHashId) - let encoded = Aeson.encode (RenderedNamespaceAndLibdepsDiff diff1) - PG.runTransaction $ - ContributionQ.savePrecomputedNamespaceDiff - (oldCodebase, oldCausalId) - (newCodebase, newCausalId) - (TL.toStrict $ TL.decodeUtf8 encoded) + diff4 <- + diff3 + & NamespaceDiffs.namespaceAndLibdepsDiffDefns_ + %%~ computeUpdatedDefinitionDiffs + authZReceipt + (oldCodebase, oldRuntime, fromMaybe oldBranchHashId maybeLcaBranchHashId) + (newCodebase, newRuntime, newBranchHashId) + let encoded = Aeson.encode (RenderedNamespaceAndLibdepsDiff diff4) + ContributionQ.savePrecomputedNamespaceDiff + (oldCodebase, oldCausalId) + (newCodebase, newCausalId) + (TL.toStrict $ TL.decodeUtf8 encoded) pure $ PreEncoded encoded computeUpdatedDefinitionDiffs :: @@ -410,10 +397,3 @@ instance ToJSON RenderedNamespaceAndLibdepsDiff where ] ) >>> toJSON @[Value] - -concurrentExceptT :: (MonadUnliftIO m) => ExceptT e m a -> ExceptT e m b -> ExceptT e m (a, b) -concurrentExceptT a b = do - (ea, eb) <- lift $ UnliftIO.concurrently (runExceptT a) (runExceptT b) - ra <- except ea - rb <- except eb - pure (ra, rb) diff --git a/src/Share/Web/Share/Projects/Impl.hs b/src/Share/Web/Share/Projects/Impl.hs index 19293df7..865d16cb 100644 --- a/src/Share/Web/Share/Projects/Impl.hs +++ b/src/Share/Web/Share/Projects/Impl.hs @@ -168,7 +168,14 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project pure (oldCausalHash, newCausalHash, maybeLcaCausalId) oldRuntime <- Codebase.codebaseRuntime oldCodebase newRuntime <- Codebase.codebaseRuntime newCodebase - namespaceDiff <- respondExceptT (Diffs.diffCausals authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId) + namespaceDiff <- + (either respondError pure =<<) do + PG.tryRunTransaction do + Diffs.diffCausals + authZReceipt + (oldCodebase, oldRuntime, oldCausalId) + (newCodebase, newRuntime, newCausalId) + maybeLcaCausalId pure ShareNamespaceDiffResponse { project = projectShortHand, From acf63d1c59ab6b3c0dbb3a01825a6b84f33f552e Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Wed, 9 Apr 2025 15:37:39 -0400 Subject: [PATCH 04/16] compute diff while holding lock on job row --- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 75 +++++++++++++------ src/Share/Codebase.hs | 22 +++--- src/Share/Metrics.hs | 34 ++++----- 3 files changed, 76 insertions(+), 55 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 917bfce9..60aafa91 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -10,6 +10,7 @@ import Share.BackgroundJobs.Workers (newWorker) import Share.Branch (Branch (..)) import Share.Codebase qualified as Codebase import Share.Contribution (Contribution (..)) +import Share.Env qualified as Env import Share.IDs import Share.IDs qualified as IDs import Share.Metrics qualified as Metrics @@ -25,6 +26,7 @@ import Share.Utils.Logging qualified as Logging import Share.Web.Authorization qualified as AuthZ import Share.Web.Errors (EntityMissing (..), ErrorID (..)) import Share.Web.Share.Diffs.Impl qualified as Diffs +import System.Clock qualified as Clock -- | Check every 30 seconds if we haven't heard on the notifications channel. -- Just in case we missed a notification. @@ -34,41 +36,66 @@ maxPollingIntervalSeconds = 30 worker :: Ki.Scope -> Background () worker scope = do authZReceipt <- AuthZ.backgroundJobAuthZ + badUnliftCodebaseRuntime <- Codebase.badAskUnliftCodebaseRuntime + unisonRuntime <- asks Env.sandboxedRuntime + let makeRuntime :: Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO) + makeRuntime codebase = do + runtime <- Codebase.codebaseRuntime' unisonRuntime codebase + pure (badUnliftCodebaseRuntime runtime) newWorker scope "diffs:contributions" $ forever do Notif.waitOnChannel Notif.ContributionDiffChannel (maxPollingIntervalSeconds * 1000000) - processDiffs authZReceipt + processDiffs authZReceipt makeRuntime -- Process diffs until we run out of them. We claim a diff in a transaction, commit it, then proceed to compute the -- diff. There's therefore a chance we claim a diff and fail to compute it (due to e.g. server restart). The current -- solution to these "at most once" semantics is to simply re-enqueue a diff job if necessary; e.g. in the view diff -- endpoint handler. -processDiffs :: AuthZ.AuthZReceipt -> Background () -processDiffs authZReceipt = do +processDiffs :: AuthZ.AuthZReceipt -> (Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO)) -> Background () +processDiffs authZReceipt makeRuntime = do let loop :: Background () loop = do - whenJustM (PG.runTransaction DQ.claimContributionToDiff) \contributionId -> do - withTag "contribution-id" (IDs.toText contributionId) do - Metrics.recordContributionDiffDuration (diffContribution authZReceipt contributionId) >>= \case - Right () -> - Logging.textLog "Computed contribution diff" - & Logging.withSeverity Logging.Info - & Logging.logMsg - Left err -> reportError err - loop + result <- + PG.runTransactionMode PG.RepeatableRead PG.ReadWrite do + DQ.claimContributionToDiff >>= \case + Nothing -> pure Nothing + Just contributionId -> do + startTime <- PG.transactionUnsafeIO (Clock.getTime Clock.Monotonic) + result <- PG.catchTransaction (diffContribution authZReceipt makeRuntime contributionId) + pure (Just (contributionId, startTime, result)) + case result of + Nothing -> pure () + Just (contributionId, startTime, result) -> do + withTag "contribution-id" (IDs.toText contributionId) do + case result of + Left err -> reportError err + Right () -> do + liftIO (Metrics.recordContributionDiffDuration startTime) + Logging.textLog "Computed contribution diff" + & Logging.withSeverity Logging.Info + & Logging.logMsg + loop loop -diffContribution :: AuthZ.AuthZReceipt -> ContributionId -> Background (Either NamespaceDiffError ()) -diffContribution authZReceipt contributionId = do - runExceptT do - (bestCommonAncestorCausalId, project, newBranch, oldBranch) <- ExceptT (PG.tryRunTransaction getContributionInfo) - let Branch {causal = oldBranchCausalId} = oldBranch - let Branch {causal = newBranchCausalId} = newBranch - let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch - let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch - oldRuntime <- lift (Codebase.codebaseRuntime oldCodebase) - newRuntime <- lift (Codebase.codebaseRuntime newCodebase) - _ <- ExceptT (PG.tryRunTransaction (Diffs.diffCausals authZReceipt (oldCodebase, oldRuntime, oldBranchCausalId) (newCodebase, newRuntime, newBranchCausalId) bestCommonAncestorCausalId)) - pure () +diffContribution :: + AuthZ.AuthZReceipt -> + (Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO)) -> + ContributionId -> + PG.Transaction NamespaceDiffError () +diffContribution authZReceipt makeRuntime contributionId = do + (bestCommonAncestorCausalId, project, newBranch, oldBranch) <- getContributionInfo + let Branch {causal = oldBranchCausalId} = oldBranch + let Branch {causal = newBranchCausalId} = newBranch + let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch + let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch + oldRuntime <- PG.transactionUnsafeIO (makeRuntime oldCodebase) + newRuntime <- PG.transactionUnsafeIO (makeRuntime newCodebase) + _ <- + Diffs.diffCausals + authZReceipt + (oldCodebase, oldRuntime, oldBranchCausalId) + (newCodebase, newRuntime, newBranchCausalId) + bestCommonAncestorCausalId + pure () where getContributionInfo :: PG.Transaction NamespaceDiffError (Maybe CausalId, Project, Branch CausalId, Branch CausalId) getContributionInfo = do diff --git a/src/Share/Codebase.hs b/src/Share/Codebase.hs index 71fc6391..a9c36a90 100644 --- a/src/Share/Codebase.hs +++ b/src/Share/Codebase.hs @@ -72,7 +72,7 @@ module Share.Codebase ) where -import Control.Concurrent.STM (TVar, atomically, modifyTVar', readTVarIO) +import Control.Concurrent.STM (TVar, atomically, modifyTVar', newTVarIO, readTVarIO) import Control.Lens import Control.Monad.Morph (hoist) import Data.ByteString.Lazy.Char8 qualified as BL @@ -182,21 +182,23 @@ codebaseEnv !_authZReceipt codebaseLoc = do codebaseRuntime :: (MonadReader (Env.Env x) m, MonadUnliftIO m) => CodebaseEnv -> m (CodebaseRuntime IO) codebaseRuntime codebase = do unisonRuntime <- asks Env.sandboxedRuntime - cacheVar <- UnliftIO.newTVarIO (CodeLookupCache mempty mempty) + rt <- liftIO (codebaseRuntime' unisonRuntime codebase) unlift <- badAskUnliftCodebaseRuntime - pure (unlift (codebaseRuntime' unisonRuntime cacheVar codebase)) + pure (unlift rt) -- | Ideally, we'd use this – a runtime with lookup actions in transaction, not IO. But that will require refactoring to -- the runtime interface in ucm, so we can't use it for now. That's bad: we end up unsafely running separate -- transactions for inner calls to 'codeLookup' / 'cachedEvalResult', which can lead to deadlock due to a starved -- connection pool. -codebaseRuntime' :: Runtime Symbol -> TVar CodeLookupCache -> CodebaseEnv -> CodebaseRuntime (PG.Transaction e) -codebaseRuntime' unisonRuntime cacheVar CodebaseEnv {codebaseOwner} = - CodebaseRuntime - { codeLookup = codeLookupForUser cacheVar codebaseOwner, - cachedEvalResult = (fmap . fmap) Term.unannotate . loadCachedEvalResult codebaseOwner, - unisonRuntime - } +codebaseRuntime' :: Runtime Symbol -> CodebaseEnv -> IO (CodebaseRuntime (PG.Transaction e)) +codebaseRuntime' unisonRuntime CodebaseEnv {codebaseOwner} = do + cacheVar <- newTVarIO (CodeLookupCache mempty mempty) + pure + CodebaseRuntime + { codeLookup = codeLookupForUser cacheVar codebaseOwner, + cachedEvalResult = (fmap . fmap) Term.unannotate . loadCachedEvalResult codebaseOwner, + unisonRuntime + } badAskUnliftCodebaseRuntime :: (MonadReader (Env.Env x) m, MonadUnliftIO m) => diff --git a/src/Share/Metrics.hs b/src/Share/Metrics.hs index 26ca013a..d1324142 100644 --- a/src/Share/Metrics.hs +++ b/src/Share/Metrics.hs @@ -14,7 +14,6 @@ module Share.Metrics ) where -import Data.Either.Combinators (whenRight) import Data.Ratio ((%)) import Data.Set qualified as Set import Data.Text qualified as Text @@ -99,12 +98,11 @@ requestMetricsMiddleware api app req handleResponse = do let path = Text.intercalate "/" <$> normalizePath api (Wai.pathInfo req) let status = Just $ Text.pack (show (HTTP.statusCode (Wai.responseStatus resp))) result <- handleResponse resp - let latency :: Double - latency = fromRational (toNanoSecs (end `diffTimeSpec` start) % 1000000000) - Prom.withLabel + recordLatency requestLatency (tShow Deployment.deployment, service, fromMaybe "" method, fromMaybe "" status, fromMaybe "unknown-path" path) - (flip Prom.observe latency) + start + end pure result else app req handleResponse where @@ -418,21 +416,13 @@ timeActionIntoHistogram histogram l m = do m `UnliftIO.finally` do liftIO do endTime <- Clock.getTime Monotonic - let latency :: Double - latency = fromRational (toNanoSecs (endTime `diffTimeSpec` startTime) % 1000000000) - Prom.withLabel histogram l (flip Prom.observe latency) + recordLatency histogram l startTime endTime --- | Like 'timeActionIntoHistogram', but only bothers to time actions that return 'Right' (indicating success). -timeRightActionIntoHistogram :: (Prom.Label l, MonadIO m) => (Prom.Vector l Prom.Histogram) -> l -> m (Either err c) -> m (Either err c) -timeRightActionIntoHistogram histogram l m = do - startTime <- liftIO $ Clock.getTime Monotonic - result <- m - whenRight result \_ -> liftIO do - endTime <- Clock.getTime Monotonic - let latency :: Double - latency = fromRational (toNanoSecs (endTime `diffTimeSpec` startTime) % 1000000000) - Prom.withLabel histogram l (flip Prom.observe latency) - pure result +recordLatency :: (Prom.Label l) => (Prom.Vector l Prom.Histogram) -> l -> Clock.TimeSpec -> Clock.TimeSpec -> IO () +recordLatency histogram l startTime endTime = do + let latency :: Double + latency = fromRational (toNanoSecs (endTime `diffTimeSpec` startTime) % 1000000000) + Prom.withLabel histogram l (flip Prom.observe latency) -- | Record the duration of a background import. recordBackgroundImportDuration :: (MonadUnliftIO m) => m r -> m r @@ -442,5 +432,7 @@ recordBackgroundImportDuration = timeActionIntoHistogram backgroundImportDuratio recordDefinitionSearchIndexDuration :: (MonadUnliftIO m) => m r -> m r recordDefinitionSearchIndexDuration = timeActionIntoHistogram definitionSearchIndexDurationSeconds (deployment, service) -recordContributionDiffDuration :: (MonadIO m) => m (Either err r) -> m (Either err r) -recordContributionDiffDuration = timeRightActionIntoHistogram contributionDiffDurationSeconds (deployment, service) +recordContributionDiffDuration :: Clock.TimeSpec -> IO () +recordContributionDiffDuration startTime = do + endTime <- Clock.getTime Monotonic + recordLatency contributionDiffDurationSeconds (deployment, service) startTime endTime From 6c7d2adf8a0b30d4a22fa00ad5c1be497573a699 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Wed, 23 Apr 2025 09:12:36 -0400 Subject: [PATCH 05/16] break diffCausals up --- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 67 +++++++--------- src/Share/Branch.hs | 2 +- src/Share/Postgres/Contributions/Queries.hs | 18 +++++ src/Share/Web/Share/Diffs/Impl.hs | 80 ++++++++++++++++++- 4 files changed, 127 insertions(+), 40 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 60aafa91..a416b8b8 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -7,7 +7,7 @@ import Share.BackgroundJobs.Diffs.Queries qualified as DQ import Share.BackgroundJobs.Errors (reportError) import Share.BackgroundJobs.Monad (Background, withTag) import Share.BackgroundJobs.Workers (newWorker) -import Share.Branch (Branch (..)) +import Share.Branch (branchCausals_) import Share.Codebase qualified as Codebase import Share.Contribution (Contribution (..)) import Share.Env qualified as Env @@ -17,11 +17,9 @@ import Share.Metrics qualified as Metrics import Share.NamespaceDiffs (NamespaceDiffError (MissingEntityError)) import Share.Postgres qualified as PG import Share.Postgres.Contributions.Queries qualified as ContributionsQ -import Share.Postgres.IDs (CausalId) import Share.Postgres.Notifications qualified as Notif import Share.Postgres.Queries qualified as Q import Share.Prelude -import Share.Project (Project) import Share.Utils.Logging qualified as Logging import Share.Web.Authorization qualified as AuthZ import Share.Web.Errors (EntityMissing (..), ErrorID (..)) @@ -60,48 +58,45 @@ processDiffs authZReceipt makeRuntime = do Nothing -> pure Nothing Just contributionId -> do startTime <- PG.transactionUnsafeIO (Clock.getTime Clock.Monotonic) - result <- PG.catchTransaction (diffContribution authZReceipt makeRuntime contributionId) + result <- PG.catchTransaction (maybeComputeAndStoreCausalDiff authZReceipt makeRuntime contributionId) pure (Just (contributionId, startTime, result)) - case result of - Nothing -> pure () - Just (contributionId, startTime, result) -> do - withTag "contribution-id" (IDs.toText contributionId) do - case result of - Left err -> reportError err - Right () -> do + whenJust result \(contributionId, startTime, result) -> do + withTag "contribution-id" (IDs.toText contributionId) do + case result of + Left err -> reportError err + Right didWork -> do + when didWork do liftIO (Metrics.recordContributionDiffDuration startTime) Logging.textLog "Computed contribution diff" & Logging.withSeverity Logging.Info & Logging.logMsg - loop + loop loop -diffContribution :: +-- Check whether a causal diff has already been computed, and if it hasn't, compute and store it. Otherwise, do nothing. +maybeComputeAndStoreCausalDiff :: AuthZ.AuthZReceipt -> (Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO)) -> ContributionId -> - PG.Transaction NamespaceDiffError () -diffContribution authZReceipt makeRuntime contributionId = do - (bestCommonAncestorCausalId, project, newBranch, oldBranch) <- getContributionInfo - let Branch {causal = oldBranchCausalId} = oldBranch - let Branch {causal = newBranchCausalId} = newBranch + PG.Transaction NamespaceDiffError Bool +maybeComputeAndStoreCausalDiff authZReceipt makeRuntime contributionId = do + Contribution {bestCommonAncestorCausalId, sourceBranchId = newBranchId, targetBranchId = oldBranchId, projectId} <- + ContributionsQ.contributionById contributionId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "contribution:missing") "Contribution not found") + project <- Q.projectById projectId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "project:missing") "Project not found") + newBranch <- Q.branchById newBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Source branch not found") + oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Target branch not found") let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch - oldRuntime <- PG.transactionUnsafeIO (makeRuntime oldCodebase) - newRuntime <- PG.transactionUnsafeIO (makeRuntime newCodebase) - _ <- - Diffs.diffCausals - authZReceipt - (oldCodebase, oldRuntime, oldBranchCausalId) - (newCodebase, newRuntime, newBranchCausalId) - bestCommonAncestorCausalId - pure () - where - getContributionInfo :: PG.Transaction NamespaceDiffError (Maybe CausalId, Project, Branch CausalId, Branch CausalId) - getContributionInfo = do - Contribution {bestCommonAncestorCausalId, sourceBranchId = newBranchId, targetBranchId = oldBranchId, projectId} <- - ContributionsQ.contributionById contributionId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "contribution:missing") "Contribution not found") - project <- Q.projectById projectId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "project:missing") "Project not found") - newBranch <- Q.branchById newBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Source branch not found") - oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Target branch not found") - pure (bestCommonAncestorCausalId, project, newBranch, oldBranch) + let oldCausal = oldBranch ^. branchCausals_ + let newCausal = newBranch ^. branchCausals_ + ContributionsQ.existsPrecomputedNamespaceDiff (oldCodebase, oldCausal) (newCodebase, newCausal) >>= \case + True -> pure False + False -> do + oldRuntime <- PG.transactionUnsafeIO (makeRuntime oldCodebase) + newRuntime <- PG.transactionUnsafeIO (makeRuntime newCodebase) + Diffs.computeAndStoreCausalDiff + authZReceipt + (oldCodebase, oldRuntime, oldCausal) + (newCodebase, newRuntime, newCausal) + bestCommonAncestorCausalId + pure True diff --git a/src/Share/Branch.hs b/src/Share/Branch.hs index 1f469746..65678169 100644 --- a/src/Share/Branch.hs +++ b/src/Share/Branch.hs @@ -55,7 +55,7 @@ instance (Hasql.DecodeValue causal) => Hasql.DecodeRow (Branch causal) where creatorId <- PG.decodeField pure $ Branch {..} -branchCausals_ :: Traversal (Branch causal) (Branch causal') causal causal' +branchCausals_ :: Lens (Branch causal) (Branch causal') causal causal' branchCausals_ f Branch {..} = (\causal -> Branch {causal, ..}) <$> f causal branchCodebaseUser :: Branch causal -> UserId diff --git a/src/Share/Postgres/Contributions/Queries.hs b/src/Share/Postgres/Contributions/Queries.hs index 53fbbd31..d2f9e7e2 100644 --- a/src/Share/Postgres/Contributions/Queries.hs +++ b/src/Share/Postgres/Contributions/Queries.hs @@ -17,6 +17,7 @@ module Share.Postgres.Contributions.Queries performMergesAndBCAUpdatesFromBranchPush, rebaseContributionsFromMergedBranches, contributionStateTokenById, + existsPrecomputedNamespaceDiff, getPrecomputedNamespaceDiff, savePrecomputedNamespaceDiff, contributionsRelatedToBranches, @@ -513,6 +514,23 @@ contributionStateTokenById contributionId = do WHERE contribution.id = #{contributionId} |] +-- | Get whether a precomputed namespace diff exists. +existsPrecomputedNamespaceDiff :: (CodebaseEnv, CausalId) -> (CodebaseEnv, CausalId) -> PG.Transaction e Bool +existsPrecomputedNamespaceDiff + (CodebaseEnv {codebaseOwner = leftCodebaseUser}, leftCausalId) + (CodebaseEnv {codebaseOwner = rightCodebaseUser}, rightCausalId) = do + PG.queryExpect1Col @Bool + [PG.sql| + SELECT EXISTS ( + SELECT + FROM namespace_diffs + WHERE left_causal_id = #{leftCausalId} + AND right_causal_id = #{rightCausalId} + AND left_codebase_owner_user_id = #{leftCodebaseUser} + AND right_codebase_owner_user_id = #{rightCodebaseUser} + ) + |] + getPrecomputedNamespaceDiff :: (CodebaseEnv, CausalId) -> (CodebaseEnv, CausalId) -> diff --git a/src/Share/Web/Share/Diffs/Impl.hs b/src/Share/Web/Share/Diffs/Impl.hs index 91c56950..05896db8 100644 --- a/src/Share/Web/Share/Diffs/Impl.hs +++ b/src/Share/Web/Share/Diffs/Impl.hs @@ -1,5 +1,6 @@ module Share.Web.Share.Diffs.Impl ( diffCausals, + computeAndStoreCausalDiff, diffTerms, diffTypes, ) @@ -16,7 +17,16 @@ import Data.Map qualified as Map import Data.Text.Lazy qualified as TL import Data.Text.Lazy.Encoding qualified as TL import Share.Codebase qualified as Codebase -import Share.NamespaceDiffs (DefinitionDiff (..), DefinitionDiffKind (..), DiffAtPath (..), GNamespaceAndLibdepsDiff, GNamespaceTreeDiff, NamespaceAndLibdepsDiff, NamespaceDiffError (..), NamespaceTreeDiff) +import Share.NamespaceDiffs + ( DefinitionDiff (..), + DefinitionDiffKind (..), + DiffAtPath (..), + GNamespaceAndLibdepsDiff, + GNamespaceTreeDiff, + NamespaceAndLibdepsDiff, + NamespaceDiffError (..), + NamespaceTreeDiff, + ) import Share.NamespaceDiffs qualified as NamespaceDiffs import Share.Postgres qualified as PG import Share.Postgres.Causal.Queries qualified as CausalQ @@ -50,13 +60,14 @@ import Unison.ShortHash (ShortHash) import Unison.Syntax.Name qualified as Name import Unison.Util.Pretty (Width) +-- | Diff two causals diffCausals :: AuthZReceipt -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> Maybe CausalId -> PG.Transaction - NamespaceDiffs.NamespaceDiffError + NamespaceDiffError ( PreEncoded ( NamespaceDiffs.NamespaceAndLibdepsDiff (TermTag, ShortHash) @@ -70,7 +81,7 @@ diffCausals :: ) diffCausals !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do -- Ensure name lookups for the things we're diffing. - let getBranch :: CausalId -> PG.Transaction NamespaceDiffs.NamespaceDiffError (BranchHashId, NameLookupReceipt) + let getBranch :: CausalId -> PG.Transaction NamespaceDiffError (BranchHashId, NameLookupReceipt) getBranch causalId = do branchHashId <- CausalQ.expectNamespaceIdsByCausalIdsOf id causalId nameLookupReceipt <- NLOps.ensureNameLookupForBranchId branchHashId @@ -164,6 +175,69 @@ diffCausals !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, n (TL.toStrict $ TL.decodeUtf8 encoded) pure $ PreEncoded encoded +-- | Diff two causals and store the diff in the database. +computeAndStoreCausalDiff :: + AuthZReceipt -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> + Maybe CausalId -> + PG.Transaction NamespaceDiffError () +computeAndStoreCausalDiff !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do + -- Ensure name lookups for the things we're diffing. + let getBranch :: CausalId -> PG.Transaction NamespaceDiffError (BranchHashId, NameLookupReceipt) + getBranch causalId = do + branchHashId <- CausalQ.expectNamespaceIdsByCausalIdsOf id causalId + nameLookupReceipt <- NLOps.ensureNameLookupForBranchId branchHashId + pure (branchHashId, nameLookupReceipt) + (oldBranchHashId, oldBranchNLReceipt) <- getBranch oldCausalId + (newBranchHashId, newBranchNLReceipt) <- getBranch newCausalId + (maybeLcaBranchHashId, maybeLcaBranchNLReceipt) <- + case maybeLcaCausalId of + Just lcaCausalId -> do + (lcaBranchHashId, lcaBranchNLReceipt) <- getBranch lcaCausalId + pure (Just lcaBranchHashId, Just lcaBranchNLReceipt) + Nothing -> pure (Nothing, Nothing) + -- Do the initial 3-way namespace diff + diff0 <- + NamespaceDiffs.computeThreeWayNamespaceDiff + TwoWay {alice = oldCodebase, bob = newCodebase} + TwoOrThreeWay {alice = oldBranchHashId, bob = newBranchHashId, lca = maybeLcaBranchHashId} + TwoOrThreeWay {alice = oldBranchNLReceipt, bob = newBranchNLReceipt, lca = maybeLcaBranchNLReceipt} + -- Resolve the term referents to tag + hash + diff1 <- + diff0 + & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferents_) + %%~ \refs -> do + termTags <- Codebase.termTagsByReferentsOf (\f -> traverse (f . referent1to2)) refs + pure $ zip termTags (refs <&> Referent.toShortHash) + -- Resolve the type references to tag + hash + diff2 <- + diff1 + & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferences_) + %%~ \refs -> do + typeTags <- Codebase.typeTagsByReferencesOf traversed refs + pure $ zip typeTags (refs <&> V2Reference.toShortHash) + -- Resolve libdeps branch hash ids to branch hashes + diff3 <- + HashQ.expectNamespaceHashesByNamespaceHashIdsOf + (NamespaceDiffs.namespaceAndLibdepsDiffLibdeps_ . traversed . traversed) + diff2 + -- Resolve the actual term/type definitions. Use the LCA as the "old" (because that's what we're rendering the + -- diff relative to, unless there isn't an LCA (unlikely), in which case we fall back on the other branch (we + -- won't have anything classified as an "update" in this case so it doesn't really matter). + diff4 <- + diff3 + & NamespaceDiffs.namespaceAndLibdepsDiffDefns_ + %%~ computeUpdatedDefinitionDiffs + authZReceipt + (oldCodebase, oldRuntime, fromMaybe oldBranchHashId maybeLcaBranchHashId) + (newCodebase, newRuntime, newBranchHashId) + let encoded = Aeson.encode (RenderedNamespaceAndLibdepsDiff diff4) + ContributionQ.savePrecomputedNamespaceDiff + (oldCodebase, oldCausalId) + (newCodebase, newCausalId) + (TL.toStrict $ TL.decodeUtf8 encoded) + computeUpdatedDefinitionDiffs :: forall a b. (Ord a, Ord b) => From 3318aa05c25e03ce2da90e756e43acb3434e21cc Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Thu, 24 Apr 2025 11:58:12 -0400 Subject: [PATCH 06/16] model diff error and diff still computing states explicitly in the API --- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 12 +- src/Share/Postgres/Causal/Queries.hs | 2 +- src/Share/Postgres/Contributions/Queries.hs | 3 +- src/Share/Postgres/Hashes/Queries.hs | 31 +- src/Share/Utils/Caching.hs | 29 +- src/Share/Web/Share/Contributions/Impl.hs | 53 +- src/Share/Web/Share/Diffs/Impl.hs | 114 +- src/Share/Web/Share/Diffs/Types.hs | 71 +- src/Share/Web/Share/Projects/Impl.hs | 48 +- .../contribution-diffs/contribution-diff.json | 4159 +++++++++-------- .../contribution-diffs/namespace-diff.json | 4159 +++++++++-------- .../merged-contribution-diff.json | 429 +- transcripts/share-apis/contributions/run.zsh | 11 + .../transitive-contribution-diff.json | 429 +- 14 files changed, 4783 insertions(+), 4767 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index a416b8b8..04877506 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -74,6 +74,7 @@ processDiffs authZReceipt makeRuntime = do loop -- Check whether a causal diff has already been computed, and if it hasn't, compute and store it. Otherwise, do nothing. +-- Returns whether or not we did any work. maybeComputeAndStoreCausalDiff :: AuthZ.AuthZReceipt -> (Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO)) -> @@ -94,9 +95,10 @@ maybeComputeAndStoreCausalDiff authZReceipt makeRuntime contributionId = do False -> do oldRuntime <- PG.transactionUnsafeIO (makeRuntime oldCodebase) newRuntime <- PG.transactionUnsafeIO (makeRuntime newCodebase) - Diffs.computeAndStoreCausalDiff - authZReceipt - (oldCodebase, oldRuntime, oldCausal) - (newCodebase, newRuntime, newCausal) - bestCommonAncestorCausalId + _ <- + Diffs.computeAndStoreCausalDiff + authZReceipt + (oldCodebase, oldRuntime, oldCausal) + (newCodebase, newRuntime, newCausal) + bestCommonAncestorCausalId pure True diff --git a/src/Share/Postgres/Causal/Queries.hs b/src/Share/Postgres/Causal/Queries.hs index 6157ebbd..8cac1104 100644 --- a/src/Share/Postgres/Causal/Queries.hs +++ b/src/Share/Postgres/Causal/Queries.hs @@ -976,7 +976,7 @@ importAccessibleCausals causalHashes = do pure results -- | Find the best common ancestor between two causals for diffs or merges. -bestCommonAncestor :: (QueryM m) => CausalId -> CausalId -> m (Maybe CausalId) +bestCommonAncestor :: (QueryA m) => CausalId -> CausalId -> m (Maybe CausalId) bestCommonAncestor a b = do query1Col [sql| SELECT best_common_causal_ancestor(#{a}, #{b}) as causal_id diff --git a/src/Share/Postgres/Contributions/Queries.hs b/src/Share/Postgres/Contributions/Queries.hs index d2f9e7e2..80019ffa 100644 --- a/src/Share/Postgres/Contributions/Queries.hs +++ b/src/Share/Postgres/Contributions/Queries.hs @@ -532,9 +532,10 @@ existsPrecomputedNamespaceDiff |] getPrecomputedNamespaceDiff :: + (PG.QueryA m) => (CodebaseEnv, CausalId) -> (CodebaseEnv, CausalId) -> - PG.Transaction e (Maybe Text) + m (Maybe Text) getPrecomputedNamespaceDiff (CodebaseEnv {codebaseOwner = leftCodebaseUser}, leftCausalId) (CodebaseEnv {codebaseOwner = rightCodebaseUser}, rightCausalId) = do diff --git a/src/Share/Postgres/Hashes/Queries.hs b/src/Share/Postgres/Hashes/Queries.hs index 34409a04..6d422a0a 100644 --- a/src/Share/Postgres/Hashes/Queries.hs +++ b/src/Share/Postgres/Hashes/Queries.hs @@ -236,30 +236,27 @@ addKnownCausalHashMismatch providedHash actualHash = do |] -- | Generic helper which fetches both branch hashes and causal hashes -expectCausalHashesOfG :: (HasCallStack, QueryM m) => ((BranchHash, CausalHash) -> h) -> Traversal s t CausalId h -> s -> m t +expectCausalHashesOfG :: (HasCallStack, QueryA m) => ((BranchHash, CausalHash) -> h) -> Traversal s t CausalId h -> s -> m t expectCausalHashesOfG project trav = do unsafePartsOf trav %%~ \hashIds -> do let numberedHashIds = zip [0 :: Int32 ..] hashIds - results :: [(BranchHash, CausalHash)] <- - queryListRows + (\results -> if length results /= length hashIds then error "expectCausalHashesOf: Missing expected causal hash" else (project <$> results)) + <$> queryListRows [sql| - WITH causal_ids(ord, id) AS ( - SELECT * FROM ^{toTable numberedHashIds} - ) - SELECT bh.base32, causal.hash - FROM causal_ids - JOIN causals causal ON causal.id = causal_ids.id - JOIN branch_hashes bh ON causal.namespace_hash_id = bh.id - ORDER BY causal_ids.ord ASC - |] - if length results /= length hashIds - then error "expectCausalHashesOf: Missing expected causal hash" - else pure (project <$> results) + WITH causal_ids(ord, id) AS ( + SELECT * FROM ^{toTable numberedHashIds} + ) + SELECT bh.base32, causal.hash + FROM causal_ids + JOIN causals causal ON causal.id = causal_ids.id + JOIN branch_hashes bh ON causal.namespace_hash_id = bh.id + ORDER BY causal_ids.ord ASC + |] -expectCausalAndBranchHashesOf :: (HasCallStack, QueryM m) => Traversal s t CausalId (BranchHash, CausalHash) -> s -> m t +expectCausalAndBranchHashesOf :: (HasCallStack, QueryA m) => Traversal s t CausalId (BranchHash, CausalHash) -> s -> m t expectCausalAndBranchHashesOf = expectCausalHashesOfG id -expectCausalHashesByIdsOf :: (HasCallStack, QueryM m) => Traversal s t CausalId CausalHash -> s -> m t +expectCausalHashesByIdsOf :: (HasCallStack, QueryA m) => Traversal s t CausalId CausalHash -> s -> m t expectCausalHashesByIdsOf = expectCausalHashesOfG snd expectCausalIdsOf :: (HasCallStack) => Traversal s t CausalHash (BranchHashId, CausalId) -> s -> CodebaseM e t diff --git a/src/Share/Utils/Caching.hs b/src/Share/Utils/Caching.hs index 5aad05df..eef64a20 100644 --- a/src/Share/Utils/Caching.hs +++ b/src/Share/Utils/Caching.hs @@ -6,6 +6,7 @@ module Share.Utils.Caching ( cachedResponse, + conditionallyCachedResponse, causalIdCacheKey, branchIdCacheKey, Cached, @@ -54,7 +55,22 @@ cachedResponse :: -- | How to generate the response if it's not in the cache. WebApp a -> WebApp (Cached ct a) -cachedResponse authzReceipt endpointName cacheParams action = do +cachedResponse authzReceipt endpointName cacheParams action = + conditionallyCachedResponse authzReceipt endpointName cacheParams ((,True) <$> action) + +-- | Like 'cachedResponse', but only cache (True, x) values. +conditionallyCachedResponse :: + forall ct a. + (Servant.MimeRender ct a) => + AuthZ.AuthZReceipt -> + -- | The name of the endpoint we're caching. Must be unique. + Text -> + -- | Cache Keys: All parameters which affect the response + [Text] -> + -- | How to generate the response if it's not in the cache. True means cache, false means don't cache. + WebApp (a, Bool) -> + WebApp (Cached ct a) +conditionallyCachedResponse authzReceipt endpointName cacheParams action = do requestIsCacheable <- shouldUseCaching let mayCachingToken = AuthZ.getCacheability authzReceipt let shouldUseCaching = requestIsCacheable && isJust mayCachingToken @@ -65,14 +81,13 @@ cachedResponse authzReceipt endpointName cacheParams action = do case mayCachedResponse of Just cachedResponse -> pure cachedResponse Nothing -> do - a <- action + (a, cache) <- action let cachedResponse :: Cached ct a cachedResponse = Cached . BL.toStrict $ Servant.mimeRender (Proxy @ct) a - -- Only actually cache the response if it's valid to do so. - case mayCachingToken of - Just ct | shouldUseCaching -> do - cacheResponse ct endpointName cacheParams $ cachedResponse - _ -> pure () + when (shouldUseCaching && cache) do + -- Only actually cache the response if it's valid to do so. + whenJust mayCachingToken \ct -> + cacheResponse ct endpointName cacheParams cachedResponse pure cachedResponse -- | Cached responses expire if not accessed in 7 days. diff --git a/src/Share/Web/Share/Contributions/Impl.hs b/src/Share/Web/Share/Contributions/Impl.hs index f6c289b8..d474f0d8 100644 --- a/src/Share/Web/Share/Contributions/Impl.hs +++ b/src/Share/Web/Share/Contributions/Impl.hs @@ -14,7 +14,9 @@ module Share.Web.Share.Contributions.Impl where import Control.Lens hiding ((.=)) +import Data.ByteString.Lazy qualified as ByteString.Lazy import Data.Set qualified as Set +import Data.Text.Encoding qualified as Text import Servant import Servant.Server.Generic (AsServerT) import Share.BackgroundJobs.Diffs.Queries qualified as DiffsQ @@ -38,6 +40,7 @@ import Share.Prelude import Share.Project import Share.User qualified as User import Share.Utils.API +import Share.Utils.Aeson (PreEncoded (..)) import Share.Utils.Caching (Cached) import Share.Utils.Caching qualified as Caching import Share.Web.App @@ -52,7 +55,7 @@ import Share.Web.Share.Contributions.API qualified as API import Share.Web.Share.Contributions.MergeDetection qualified as MergeDetection import Share.Web.Share.Contributions.Types import Share.Web.Share.Diffs.Impl qualified as Diffs -import Share.Web.Share.Diffs.Types (ShareNamespaceDiffResponse (..), ShareTermDiffResponse (..), ShareTypeDiffResponse (..)) +import Share.Web.Share.Diffs.Types (ShareNamespaceDiffResponse (..), ShareNamespaceDiffStatus (..), ShareTermDiffResponse (..), ShareTypeDiffResponse (..)) import Share.Web.Share.DisplayInfo (UserDisplayInfo (..)) import Unison.Name (Name) import Unison.Server.Types @@ -261,7 +264,7 @@ contributionDiffEndpoint :: WebApp (Cached JSON ShareNamespaceDiffResponse) contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle projectSlug contributionNumber = do ( project@Project {projectId}, - Contribution {contributionId, bestCommonAncestorCausalId}, + Contribution {contributionId}, oldBranch@Branch {causal = oldBranchCausalId, branchId = oldBranchId}, newBranch@Branch {causal = newBranchCausalId, branchId = newBranchId} ) <- PG.runTransactionOrRespondError $ do @@ -279,30 +282,28 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr lift $ Q.projectBranchShortHandByBranchId newBranchId `whenNothingM` throwError (EntityMissing (ErrorID "branch:missing") "Source branch not found") let cacheKeys = [IDs.toText contributionId, IDs.toText newPBSH, IDs.toText oldPBSH, Caching.causalIdCacheKey newBranchCausalId, Caching.causalIdCacheKey oldBranchCausalId] - Caching.cachedResponse authZReceipt "contribution-diff" cacheKeys do - oldRuntime <- Codebase.codebaseRuntime oldCodebase - newRuntime <- Codebase.codebaseRuntime newCodebase - namespaceDiff <- - (either respondError pure =<<) do - PG.tryRunTransaction do - Diffs.diffCausals - authZReceipt - (oldCodebase, oldRuntime, oldBranchCausalId) - (newCodebase, newRuntime, newBranchCausalId) - bestCommonAncestorCausalId - (newBranchCausalHash, oldBranchCausalHash) <- PG.runTransaction do - newBranchCausalHash <- CausalQ.expectCausalHashesByIdsOf id newBranchCausalId - oldBranchCausalHash <- CausalQ.expectCausalHashesByIdsOf id oldBranchCausalId - pure (newBranchCausalHash, oldBranchCausalHash) - pure $ - ShareNamespaceDiffResponse - { project = projectShorthand, - newRef = IDs.IsBranchShortHand $ IDs.projectBranchShortHandToBranchShortHand newPBSH, - newRefHash = Just $ PrefixedHash newBranchCausalHash, - oldRef = IDs.IsBranchShortHand $ IDs.projectBranchShortHandToBranchShortHand oldPBSH, - oldRefHash = Just $ PrefixedHash oldBranchCausalHash, - diff = namespaceDiff - } + Caching.conditionallyCachedResponse authZReceipt "contribution-diff" cacheKeys do + (oldBranchCausalHash, newBranchCausalHash, maybeNamespaceDiff) <- + PG.runTransaction do + PG.pipelined do + (,,) + <$> CausalQ.expectCausalHashesByIdsOf id oldBranchCausalId + <*> CausalQ.expectCausalHashesByIdsOf id newBranchCausalId + <*> ContributionsQ.getPrecomputedNamespaceDiff (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) + let response = + ShareNamespaceDiffResponse + { project = projectShorthand, + newRef = IDs.IsBranchShortHand $ IDs.projectBranchShortHandToBranchShortHand newPBSH, + newRefHash = Just $ PrefixedHash newBranchCausalHash, + oldRef = IDs.IsBranchShortHand $ IDs.projectBranchShortHandToBranchShortHand oldPBSH, + oldRefHash = Just $ PrefixedHash oldBranchCausalHash, + diff = + case maybeNamespaceDiff of + Just diff -> ShareNamespaceDiffStatus'Ok (PreEncoded (ByteString.Lazy.fromStrict (Text.encodeUtf8 diff))) + Nothing -> ShareNamespaceDiffStatus'StillComputing + } + let shouldCache = isJust maybeNamespaceDiff + pure (response, shouldCache) where projectShorthand = IDs.ProjectShortHand {userHandle, projectSlug} diff --git a/src/Share/Web/Share/Diffs/Impl.hs b/src/Share/Web/Share/Diffs/Impl.hs index 05896db8..3982ab6a 100644 --- a/src/Share/Web/Share/Diffs/Impl.hs +++ b/src/Share/Web/Share/Diffs/Impl.hs @@ -1,6 +1,5 @@ module Share.Web.Share.Diffs.Impl - ( diffCausals, - computeAndStoreCausalDiff, + ( computeAndStoreCausalDiff, diffTerms, diffTypes, ) @@ -21,7 +20,6 @@ import Share.NamespaceDiffs ( DefinitionDiff (..), DefinitionDiffKind (..), DiffAtPath (..), - GNamespaceAndLibdepsDiff, GNamespaceTreeDiff, NamespaceAndLibdepsDiff, NamespaceDiffError (..), @@ -49,8 +47,6 @@ import Unison.Merge qualified as Merge import Unison.Name (Name) import Unison.NameSegment (NameSegment) import Unison.PrettyPrintEnvDecl qualified as PPED -import Unison.Reference (TypeReference) -import Unison.Referent (Referent) import Unison.Referent qualified as Referent import Unison.Server.Backend.DefinitionDiff qualified as DefinitionDiff import Unison.Server.NameSearch.Postgres qualified as PGNameSearch @@ -60,8 +56,8 @@ import Unison.ShortHash (ShortHash) import Unison.Syntax.Name qualified as Name import Unison.Util.Pretty (Width) --- | Diff two causals -diffCausals :: +-- | Diff two causals and store the diff in the database. +computeAndStoreCausalDiff :: AuthZReceipt -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> @@ -79,109 +75,6 @@ diffCausals :: BranchHash ) ) -diffCausals !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do - -- Ensure name lookups for the things we're diffing. - let getBranch :: CausalId -> PG.Transaction NamespaceDiffError (BranchHashId, NameLookupReceipt) - getBranch causalId = do - branchHashId <- CausalQ.expectNamespaceIdsByCausalIdsOf id causalId - nameLookupReceipt <- NLOps.ensureNameLookupForBranchId branchHashId - pure (branchHashId, nameLookupReceipt) - (oldBranchHashId, oldBranchNLReceipt) <- getBranch oldCausalId - (newBranchHashId, newBranchNLReceipt) <- getBranch newCausalId - ContributionQ.getPrecomputedNamespaceDiff (oldCodebase, oldCausalId) (newCodebase, newCausalId) >>= \case - Just diff -> pure $ PreEncoded $ TL.encodeUtf8 $ TL.fromStrict diff - Nothing -> do - (maybeLcaBranchHashId, maybeLcaBranchNLReceipt) <- - case maybeLcaCausalId of - Just lcaCausalId -> do - (lcaBranchHashId, lcaBranchNLReceipt) <- getBranch lcaCausalId - pure (Just lcaBranchHashId, Just lcaBranchNLReceipt) - Nothing -> pure (Nothing, Nothing) - -- Do the initial 3-way namespace diff - diff0 :: - GNamespaceAndLibdepsDiff - NameSegment - Referent - TypeReference - Name - Name - Name - Name - BranchHashId <- - NamespaceDiffs.computeThreeWayNamespaceDiff - TwoWay {alice = oldCodebase, bob = newCodebase} - TwoOrThreeWay {alice = oldBranchHashId, bob = newBranchHashId, lca = maybeLcaBranchHashId} - TwoOrThreeWay {alice = oldBranchNLReceipt, bob = newBranchNLReceipt, lca = maybeLcaBranchNLReceipt} - -- Resolve the term referents to tag + hash - diff1 :: - GNamespaceAndLibdepsDiff - NameSegment - (TermTag, ShortHash) - TypeReference - Name - Name - Name - Name - BranchHashId <- - diff0 - & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferents_) - %%~ \refs -> do - termTags <- Codebase.termTagsByReferentsOf (\f -> traverse (f . referent1to2)) refs - pure $ zip termTags (refs <&> Referent.toShortHash) - -- Resolve the type references to tag + hash - diff2 :: - GNamespaceAndLibdepsDiff - NameSegment - (TermTag, ShortHash) - (TypeTag, ShortHash) - Name - Name - Name - Name - BranchHashId <- - diff1 - & unsafePartsOf (NamespaceDiffs.namespaceAndLibdepsDiffDefns_ . NamespaceDiffs.namespaceTreeDiffReferences_) - %%~ \refs -> do - typeTags <- Codebase.typeTagsByReferencesOf traversed refs - pure $ zip typeTags (refs <&> V2Reference.toShortHash) - -- Resolve libdeps branch hash ids to branch hashes - diff3 :: - GNamespaceAndLibdepsDiff - NameSegment - (TermTag, ShortHash) - (TypeTag, ShortHash) - Name - Name - Name - Name - BranchHash <- - HashQ.expectNamespaceHashesByNamespaceHashIdsOf - (NamespaceDiffs.namespaceAndLibdepsDiffLibdeps_ . traversed . traversed) - diff2 - -- Resolve the actual term/type definitions. Use the LCA as the "old" (because that's what we're rendering the - -- diff relative to, unless there isn't an LCA (unlikely), in which case we fall back on the other branch (we - -- won't have anything classified as an "update" in this case so it doesn't really matter). - diff4 <- - diff3 - & NamespaceDiffs.namespaceAndLibdepsDiffDefns_ - %%~ computeUpdatedDefinitionDiffs - authZReceipt - (oldCodebase, oldRuntime, fromMaybe oldBranchHashId maybeLcaBranchHashId) - (newCodebase, newRuntime, newBranchHashId) - let encoded = Aeson.encode (RenderedNamespaceAndLibdepsDiff diff4) - ContributionQ.savePrecomputedNamespaceDiff - (oldCodebase, oldCausalId) - (newCodebase, newCausalId) - (TL.toStrict $ TL.decodeUtf8 encoded) - pure $ PreEncoded encoded - --- | Diff two causals and store the diff in the database. -computeAndStoreCausalDiff :: - AuthZReceipt -> - (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> - (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> - Maybe CausalId -> - PG.Transaction NamespaceDiffError () computeAndStoreCausalDiff !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do -- Ensure name lookups for the things we're diffing. let getBranch :: CausalId -> PG.Transaction NamespaceDiffError (BranchHashId, NameLookupReceipt) @@ -237,6 +130,7 @@ computeAndStoreCausalDiff !authZReceipt (oldCodebase, oldRuntime, oldCausalId) ( (oldCodebase, oldCausalId) (newCodebase, newCausalId) (TL.toStrict $ TL.decodeUtf8 encoded) + pure (PreEncoded encoded) computeUpdatedDefinitionDiffs :: forall a b. diff --git a/src/Share/Web/Share/Diffs/Types.hs b/src/Share/Web/Share/Diffs/Types.hs index 3ac48952..0d532a88 100644 --- a/src/Share/Web/Share/Diffs/Types.hs +++ b/src/Share/Web/Share/Diffs/Types.hs @@ -4,23 +4,90 @@ module Share.Web.Share.Diffs.Types where import Data.Aeson import Share.IDs -import Share.NamespaceDiffs (NamespaceAndLibdepsDiff) +import Share.NamespaceDiffs (NamespaceAndLibdepsDiff, NamespaceDiffError) +import Share.NamespaceDiffs qualified as NamespaceDiffs import Share.Postgres.IDs (BranchHash, CausalHash) import Share.Prelude import Share.Utils.Aeson (PreEncoded) +import Unison.Merge (IncoherentDeclReason (..)) +import Unison.Merge.EitherWay qualified as EitherWay import Unison.Server.Types (DisplayObjectDiff (..), TermDefinition, TermDefinitionDiff (..), TermTag, TypeDefinition, TypeDefinitionDiff (..), TypeTag) import Unison.ShortHash (ShortHash) type ShareNamespaceDiff = NamespaceAndLibdepsDiff (TermTag, ShortHash) (TypeTag, ShortHash) TermDefinition TypeDefinition TermDefinitionDiff TypeDefinitionDiff BranchHash +data ShareNamespaceDiffStatus + = ShareNamespaceDiffStatus'Ok (PreEncoded ShareNamespaceDiff) + | ShareNamespaceDiffStatus'Error NamespaceDiffError + | ShareNamespaceDiffStatus'StillComputing + +instance ToJSON ShareNamespaceDiffStatus where + toJSON = \case + ShareNamespaceDiffStatus'Ok diff -> + object + [ "diff" .= diff, + "diffKind" .= ("ok" :: Text) + ] + ShareNamespaceDiffStatus'Error err -> + object + [ "diffKind" .= ("error" :: Text), + "error" + .= case err of + NamespaceDiffs.ImpossibleError _ -> + object + [ "errorKind" .= ("impossibleError" :: Text) + ] + NamespaceDiffs.IncoherentDecl reason -> + let f :: Text -> IncoherentDeclReason -> Value + f which reason = + object + ( "oldOrNewBranch" .= which + : case reason of + IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> + [ "errorKind" .= ("constructorAlias" :: Text), + "typeName" .= typeName, + "constructorName1" .= constructorName1, + "constructorName2" .= constructorName2 + ] + IncoherentDeclReason'MissingConstructorName typeName -> + [ "errorKind" .= ("missingConstructorName" :: Text), + "typeName" .= typeName + ] + IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> + [ "errorKind" .= ("constructorAlias" :: Text), + "constructorName1" .= constructorName1, + "constructorName2" .= constructorName2 + ] + IncoherentDeclReason'StrayConstructor _ constructorName -> + [ "errorKind" .= ("strayConstructor" :: Text), + "constructorName" .= constructorName + ] + ) + in case reason of + EitherWay.Alice reason -> f "old" reason + EitherWay.Bob reason -> f "new" reason + NamespaceDiffs.LibFoundAtUnexpectedPath _ -> + object + [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) + ] + NamespaceDiffs.MissingEntityError _ -> + object + [ "errorKind" .= ("missingEntityError" :: Text) + ] + ] + ShareNamespaceDiffStatus'StillComputing -> + object + [ "diffKind" .= ("computing" :: Text) + ] + data ShareNamespaceDiffResponse = ShareNamespaceDiffResponse { project :: ProjectShortHand, oldRef :: BranchOrReleaseShortHand, oldRefHash :: Maybe (PrefixedHash "#" CausalHash), newRef :: BranchOrReleaseShortHand, newRefHash :: Maybe (PrefixedHash "#" CausalHash), - diff :: PreEncoded ShareNamespaceDiff + diff :: ShareNamespaceDiffStatus } instance ToJSON ShareNamespaceDiffResponse where diff --git a/src/Share/Web/Share/Projects/Impl.hs b/src/Share/Web/Share/Projects/Impl.hs index 865d16cb..d638f537 100644 --- a/src/Share/Web/Share/Projects/Impl.hs +++ b/src/Share/Web/Share/Projects/Impl.hs @@ -8,6 +8,7 @@ module Share.Web.Share.Projects.Impl where import Control.Lens import Control.Monad.Except import Data.ByteString.Lazy qualified as BL +import Data.ByteString.Lazy qualified as ByteString.Lazy import Data.Map qualified as Map import Data.Text qualified as Text import Data.Text.Encoding qualified as Text @@ -16,12 +17,14 @@ import Share.Branch (defaultBranchShorthand) import Share.Branch qualified as Branch import Share.Codebase (CodebaseEnv) import Share.Codebase qualified as Codebase +import Share.Env qualified as Env import Share.IDs (PrefixedHash (..), ProjectSlug (..), UserHandle, UserId) import Share.IDs qualified as IDs import Share.OAuth.Session import Share.Postgres qualified as PG import Share.Postgres.Authorization.Queries qualified as AuthZQ import Share.Postgres.Causal.Queries qualified as CausalQ +import Share.Postgres.Contributions.Queries qualified as ContributionsQ import Share.Postgres.IDs (BranchHashId, CausalId) import Share.Postgres.Ops qualified as PGO import Share.Postgres.Projects.Queries qualified as ProjectsQ @@ -32,6 +35,7 @@ import Share.Project (Project (..)) import Share.Release qualified as Release import Share.User (User (..)) import Share.Utils.API ((:++) (..)) +import Share.Utils.Aeson (PreEncoded (..)) import Share.Utils.Caching (Cached) import Share.Utils.Caching qualified as Caching import Share.Utils.Logging qualified as Logging @@ -43,7 +47,7 @@ import Share.Web.Errors import Share.Web.Share.Branches.Impl (branchesServer, getProjectBranchReadmeEndpoint) import Share.Web.Share.Contributions.Impl (contributionsByProjectServer) import Share.Web.Share.Diffs.Impl qualified as Diffs -import Share.Web.Share.Diffs.Types (ShareNamespaceDiffResponse (..), ShareTermDiffResponse (..), ShareTypeDiffResponse (..)) +import Share.Web.Share.Diffs.Types (ShareNamespaceDiffResponse (..), ShareNamespaceDiffStatus (..), ShareTermDiffResponse (..), ShareTypeDiffResponse (..)) import Share.Web.Share.Projects.API qualified as API import Share.Web.Share.Projects.Types import Share.Web.Share.Releases.Impl (getProjectReleaseReadmeEndpoint, releasesServer) @@ -161,21 +165,30 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project let cacheKeys = [IDs.toText projectId, IDs.toText oldShortHand, IDs.toText newShortHand, Caching.causalIdCacheKey oldCausalId, Caching.causalIdCacheKey newCausalId] Caching.cachedResponse authZReceipt "project-diff-namespaces" cacheKeys do - (oldCausalHash, newCausalHash, maybeLcaCausalId) <- + ((oldCausalHash, newCausalHash), maybeLcaCausalId) <- PG.runTransaction do - (oldCausalHash, newCausalHash) <- CausalQ.expectCausalHashesByIdsOf each (oldCausalId, newCausalId) - maybeLcaCausalId <- CausalQ.bestCommonAncestor oldCausalId newCausalId - pure (oldCausalHash, newCausalHash, maybeLcaCausalId) - oldRuntime <- Codebase.codebaseRuntime oldCodebase - newRuntime <- Codebase.codebaseRuntime newCodebase - namespaceDiff <- - (either respondError pure =<<) do - PG.tryRunTransaction do - Diffs.diffCausals - authZReceipt - (oldCodebase, oldRuntime, oldCausalId) - (newCodebase, newRuntime, newCausalId) - maybeLcaCausalId + PG.pipelined do + (,) + <$> CausalQ.expectCausalHashesByIdsOf each (oldCausalId, newCausalId) + <*> CausalQ.bestCommonAncestor oldCausalId newCausalId + badUnliftCodebaseRuntime <- Codebase.badAskUnliftCodebaseRuntime + unisonRuntime <- asks Env.sandboxedRuntime + let makeRuntime :: Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO) + makeRuntime codebase = do + runtime <- Codebase.codebaseRuntime' unisonRuntime codebase + pure (badUnliftCodebaseRuntime runtime) + diffOrError <- + PG.tryRunTransaction do + ContributionsQ.getPrecomputedNamespaceDiff (oldCodebase, oldCausalId) (newCodebase, newCausalId) >>= \case + Just diff -> pure (PreEncoded (ByteString.Lazy.fromStrict (Text.encodeUtf8 diff))) + Nothing -> do + oldRuntime <- PG.transactionUnsafeIO (makeRuntime oldCodebase) + newRuntime <- PG.transactionUnsafeIO (makeRuntime newCodebase) + Diffs.computeAndStoreCausalDiff + authZReceipt + (oldCodebase, oldRuntime, oldCausalId) + (newCodebase, newRuntime, newCausalId) + maybeLcaCausalId pure ShareNamespaceDiffResponse { project = projectShortHand, @@ -183,7 +196,10 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project oldRefHash = Just $ PrefixedHash oldCausalHash, newRef = newShortHand, newRefHash = Just $ PrefixedHash newCausalHash, - diff = namespaceDiff + diff = + case diffOrError of + Right diff -> ShareNamespaceDiffStatus'Ok diff + Left err -> ShareNamespaceDiffStatus'Error err } where projectShortHand = IDs.ProjectShortHand {userHandle, projectSlug} diff --git a/transcripts/share-apis/contribution-diffs/contribution-diff.json b/transcripts/share-apis/contribution-diffs/contribution-diff.json index db781a63..b50d9313 100644 --- a/transcripts/share-apis/contribution-diffs/contribution-diff.json +++ b/transcripts/share-apis/contribution-diffs/contribution-diff.json @@ -1,615 +1,180 @@ { "body": { "diff": { - "defns": { - "changes": [ - { - "contents": { + "diff": { + "defns": { + "changes": [ + { "contents": { - "aliasFullName": "ATypeAlias", - "aliasShortName": "ATypeAlias", - "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", - "otherNames": [ - "DataAliasMe" - ], - "rendered": { - "bestTypeName": "ATypeAlias", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "ATypeAlias", - "tag": "HashQualifier" - }, - "segment": "ATypeAlias" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", - "tag": "TermReference" - }, - "segment": "B" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "ATypeAlias", + "contents": { + "aliasFullName": "ATypeAlias", + "aliasShortName": "ATypeAlias", + "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", + "otherNames": [ "DataAliasMe" - ] - } - }, - "tag": "Aliased" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "aliasFullName": "AbilityAlias", - "aliasShortName": "AbilityAlias", - "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "otherNames": [ - "AbilityAliasMe" - ], - "rendered": { - "bestTypeName": "AbilityAlias", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityAlias", - "tag": "HashQualifier" - }, - "segment": "AbilityAlias" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", - "tag": "TermReference" - }, - "segment": "abilityAliasMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "tag": "TypeReference" - }, - "segment": "AbilityAlias" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityAlias", - "AbilityAliasMe" - ] - } - }, - "tag": "Aliased" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "fullName": "AbilityDeleteMe", - "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", - "rendered": { - "bestTypeName": "AbilityDeleteMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityDeleteMe", - "tag": "HashQualifier" - }, - "segment": "AbilityDeleteMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", - "tag": "TermReference" - }, - "segment": "abilityDeleteMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", - "tag": "TypeReference" - }, - "segment": "AbilityDeleteMe" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityDeleteMe" - ] - }, - "shortName": "AbilityDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "fullName": "AbilityNew", - "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", - "rendered": { - "bestTypeName": "AbilityNew", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityNew", - "tag": "HashQualifier" - }, - "segment": "AbilityNew" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", - "tag": "TermReference" - }, - "segment": "abilityNew" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" + ], + "rendered": { + "bestTypeName": "ATypeAlias", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "segment": "{" - }, - { - "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "AbilityNew" - }, - { - "annotation": { - "tag": "AbilityBraces" + { + "annotation": { + "contents": "ATypeAlias", + "tag": "HashQualifier" + }, + "segment": "ATypeAlias" }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " }, - "segment": "Text" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityNew" - ] + { + "annotation": { + "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", + "tag": "TermReference" + }, + "segment": "B" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "ATypeAlias", + "DataAliasMe" + ] + } }, - "shortName": "AbilityNew" + "tag": "Aliased" }, - "tag": "Added" + "tag": "Data" }, - "tag": "Ability" - }, - { - "contents": { + { "contents": { - "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", - "newFullName": "AbilityRenamed", - "newShortName": "AbilityRenamed", - "oldNames": [ - "AbilityRenameMe" - ], - "rendered": { - "bestTypeName": "AbilityRenamed", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityRenamed", - "tag": "HashQualifier" - }, - "segment": "AbilityRenamed" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", - "tag": "TermReference" - }, - "segment": "abilityRenameMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" + "contents": { + "aliasFullName": "AbilityAlias", + "aliasShortName": "AbilityAlias", + "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", + "otherNames": [ + "AbilityAliasMe" + ], + "rendered": { + "bestTypeName": "AbilityAlias", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" }, - "segment": "{" - }, - { - "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "AbilityRenamed" - }, - { - "annotation": { - "tag": "AbilityBraces" + { + "annotation": { + "contents": "AbilityAlias", + "tag": "HashQualifier" + }, + "segment": "AbilityAlias" }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityRenamed" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": null, + "segment": " " }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", "tag": "TermReference" }, - "segment": "abilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", - "tag": "TermReference" - } + "segment": "abilityAliasMe" }, { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - } - ] + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "tag": "TypeReference" + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - "segment": "AbilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "segment": "{" + }, + { + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", "tag": "TypeReference" - } + }, + "segment": "AbilityAlias" }, { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" }, { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] + "annotation": null, + "segment": " " }, { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ] + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" } ], "tag": "UserObject" }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "AbilityUpdateMe", + "typeDocs": [], + "typeNames": [ + "AbilityAlias", + "AbilityAliasMe" + ] + } + }, + "tag": "Aliased" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityDeleteMe", + "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "rendered": { + "bestTypeName": "AbilityDeleteMe", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -625,10 +190,10 @@ }, { "annotation": { - "contents": "AbilityUpdateMe", + "contents": "AbilityDeleteMe", "tag": "HashQualifier" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityDeleteMe" }, { "annotation": { @@ -646,10 +211,10 @@ }, { "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", "tag": "TermReference" }, - "segment": "abilityUpdateMe" + "segment": "abilityDeleteMe" }, { "annotation": { @@ -669,10 +234,10 @@ }, { "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", "tag": "TypeReference" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityDeleteMe" }, { "annotation": { @@ -696,11 +261,22 @@ }, "typeDocs": [], "typeNames": [ - "AbilityUpdateMe" + "AbilityDeleteMe" ] }, - "right": { - "bestTypeName": "AbilityUpdateMe", + "shortName": "AbilityDeleteMe" + }, + "tag": "Removed" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityNew", + "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "rendered": { + "bestTypeName": "AbilityNew", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -716,10 +292,10 @@ }, { "annotation": { - "contents": "AbilityUpdateMe", + "contents": "AbilityNew", "tag": "HashQualifier" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityNew" }, { "annotation": { @@ -737,10 +313,10 @@ }, { "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", "tag": "TermReference" }, - "segment": "abilityUpdateMe" + "segment": "abilityNew" }, { "annotation": { @@ -760,10 +336,10 @@ }, { "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", "tag": "TypeReference" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityNew" }, { "annotation": { @@ -787,195 +363,453 @@ }, "typeDocs": [], "typeNames": [ - "AbilityUpdateMe" + "AbilityNew" ] - } + }, + "shortName": "AbilityNew" }, - "fullName": "AbilityUpdateMe", - "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "newTag": "Ability", - "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "oldTag": "Ability", - "shortName": "AbilityUpdateMe" + "tag": "Added" }, - "tag": "Updated" + "tag": "Ability" }, - "tag": "Ability" - }, - { - "contents": { + { "contents": { - "fullName": "DataDeleteMe", - "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", - "rendered": { - "bestTypeName": "DataDeleteMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" + "contents": { + "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "newFullName": "AbilityRenamed", + "newShortName": "AbilityRenamed", + "oldNames": [ + "AbilityRenameMe" + ], + "rendered": { + "bestTypeName": "AbilityRenamed", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataDeleteMe", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "DataDeleteMe" - }, - { - "annotation": { - "tag": "DelimiterChar" + { + "annotation": { + "contents": "AbilityRenamed", + "tag": "HashQualifier" + }, + "segment": "AbilityRenamed" }, - "segment": " = " - }, - { - "annotation": { - "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", - "tag": "TermReference" + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" }, - "segment": "C" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataDeleteMe" - ] + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", + "tag": "TermReference" + }, + "segment": "abilityRenameMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "tag": "TypeReference" + }, + "segment": "AbilityRenamed" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityRenamed" + ] + } }, - "shortName": "DataDeleteMe" + "tag": "RenamedFrom" }, - "tag": "Removed" + "tag": "Ability" }, - "tag": "Data" - }, - { - "contents": { + { "contents": { - "diff": { + "contents": { "diff": { "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "tag": "TermReference" + }, + "segment": "abilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "tag": "TermReference" + } + }, + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "tag": "TypeReference" + }, + "segment": "AbilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "tag": "TypeReference" + } + }, + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" }, - "segment": "type" + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTypeName": "AbilityUpdateMe", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "tag": "TermReference" + }, + "segment": "abilityUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "tag": "TypeReference" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityUpdateMe" + ] + }, + "right": { + "bestTypeName": "AbilityUpdateMe", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "tag": "TermReference" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" - }, - "segment": "D" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", - "tag": "TermReference" - }, - "segment": "D2" + "segment": "abilityUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "DataUpdateMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" + "segment": "{" }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" + { + "annotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "tag": "TypeReference" + }, + "segment": "AbilityUpdateMe" }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" }, - "segment": " = " - }, - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" + { + "annotation": null, + "segment": " " }, - "segment": "D" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataUpdateMe" - ] + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityUpdateMe" + ] + } }, - "right": { - "bestTypeName": "DataUpdateMe", + "fullName": "AbilityUpdateMe", + "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "newTag": "Ability", + "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "oldTag": "Ability", + "shortName": "AbilityUpdateMe" + }, + "tag": "Updated" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "DataDeleteMe", + "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", + "rendered": { + "bestTypeName": "DataDeleteMe", "defnTypeTag": "Data", "typeDefinition": { "contents": [ @@ -991,10 +825,10 @@ }, { "annotation": { - "contents": "DataUpdateMe", + "contents": "DataDeleteMe", "tag": "HashQualifier" }, - "segment": "DataUpdateMe" + "segment": "DataDeleteMe" }, { "annotation": { @@ -1004,917 +838,573 @@ }, { "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", "tag": "TermReference" }, - "segment": "D2" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" + "segment": "C" } ], "tag": "UserObject" }, "typeDocs": [], "typeNames": [ - "DataUpdateMe" + "DataDeleteMe" ] - } - }, - "fullName": "DataUpdateMe", - "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", - "newTag": "Data", - "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", - "oldTag": "Data", - "shortName": "DataUpdateMe" - }, - "tag": "Updated" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "fullName": "NewType", - "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", - "rendered": { - "bestTypeName": "NewType", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "NewType", - "tag": "HashQualifier" - }, - "segment": "NewType" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", - "tag": "TermReference" - }, - "segment": "X" - } - ], - "tag": "UserObject" }, - "typeDocs": [], - "typeNames": [ - "NewType" - ] + "shortName": "DataDeleteMe" }, - "shortName": "NewType" + "tag": "Removed" }, - "tag": "Added" + "tag": "Data" }, - "tag": "Data" - }, - { - "contents": { + { "contents": { - "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", - "newFullName": "RenamedType", - "newShortName": "RenamedType", - "oldNames": [ - "DataRenameMe" - ], - "rendered": { - "bestTypeName": "RenamedType", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", + "tag": "TermReference" + }, + "segment": "D" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] + } + ], + "tag": "UserObject" }, - { - "annotation": { - "contents": "RenamedType", - "tag": "HashQualifier" - }, - "segment": "RenamedType" + "diffKind": "diff" + }, + "left": { + "bestTypeName": "DataUpdateMe", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", + "tag": "TermReference" + }, + "segment": "D" + } + ], + "tag": "UserObject" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " + "typeDocs": [], + "typeNames": [ + "DataUpdateMe" + ] + }, + "right": { + "bestTypeName": "DataUpdateMe", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" }, - { - "annotation": { - "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", - "tag": "TermReference" - }, - "segment": "E" - } - ], - "tag": "UserObject" + "typeDocs": [], + "typeNames": [ + "DataUpdateMe" + ] + } }, - "typeDocs": [], - "typeNames": [ - "RenamedType" - ] - } + "fullName": "DataUpdateMe", + "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", + "newTag": "Data", + "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", + "oldTag": "Data", + "shortName": "DataUpdateMe" + }, + "tag": "Updated" }, - "tag": "RenamedFrom" + "tag": "Data" }, - "tag": "Data" - }, - { - "contents": { + { "contents": { - "fullName": "aDoc", - "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - "rendered": { - "bestTermName": "aDoc", - "defnTermTag": "Doc", - "signature": [ - { - "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" - }, - "segment": "Doc2" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" - }, - "segment": "aDoc" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" - }, - "segment": "Doc2" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" + "contents": { + "fullName": "NewType", + "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", + "rendered": { + "bestTypeName": "NewType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "segment": "aDoc" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": " " }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "DocDelimiter" + { + "annotation": { + "contents": "NewType", + "tag": "HashQualifier" + }, + "segment": "NewType" }, - "segment": "{{" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": null, - "segment": "Test" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": null, - "segment": "Doc" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "DocDelimiter" + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " }, - "segment": "}}" - } - ], - "tag": "UserObject" - }, - "termDocs": [ - [ - "aDoc", - "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - { - "contents": [ - { - "contents": "Test", - "tag": "Word" + { + "annotation": { + "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", + "tag": "TermReference" }, - { - "contents": "Doc", - "tag": "Word" - } - ], - "tag": "Paragraph" - } + "segment": "X" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "NewType" ] - ], - "termNames": [ - "aDoc" - ] + }, + "shortName": "NewType" }, - "shortName": "aDoc" + "tag": "Added" }, - "tag": "Removed" + "tag": "Data" }, - "tag": "Doc" - }, - { - "contents": { + { "contents": { - "aliasFullName": "aTermAlias", - "aliasShortName": "aTermAlias", - "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", - "otherNames": [ - "termAliasMe" - ], - "rendered": { - "bestTermName": "aTermAlias", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } + "contents": { + "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", + "newFullName": "RenamedType", + "newShortName": "RenamedType", + "oldNames": [ + "DataRenameMe" ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" - }, - "segment": "aTermAlias" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "rendered": { + "bestTypeName": "RenamedType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "aTermAlias" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "contents": "RenamedType", + "tag": "HashQualifier" + }, + "segment": "RenamedType" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " }, - "segment": "1" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "aTermAlias", - "termAliasMe" - ] - } + { + "annotation": { + "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", + "tag": "TermReference" + }, + "segment": "E" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "RenamedType" + ] + } + }, + "tag": "RenamedFrom" }, - "tag": "Aliased" + "tag": "Data" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "fullName": "aTest", - "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", - "rendered": { - "bestTermName": "aTest", - "defnTermTag": "Test", - "signature": [ - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", - "tag": "TypeReference" - }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "]" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aTest", - "tag": "HashQualifier" - }, - "segment": "aTest" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, + "contents": { + "fullName": "aDoc", + "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + "rendered": { + "bestTermName": "aDoc", + "defnTermTag": "Doc", + "signature": [ { "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", "tag": "TypeReference" }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" + "segment": "Doc2" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" }, - "segment": "]" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "aTest", - "tag": "HashQualifier" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": "aTest" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": " " }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" + { + "annotation": { + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", + "tag": "TypeReference" + }, + "segment": "Doc2" }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", - "tag": "TermReference" + { + "annotation": null, + "segment": "\n" }, - "segment": "Ok" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" }, - "segment": "\"Done\"" - }, - { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" }, - "segment": "]" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "aTest" - ] - }, - "shortName": "aTest" - }, - "tag": "Removed" - }, - "tag": "Test" - }, - { - "contents": { - "contents": { - "fullName": "newTerm", - "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", - "rendered": { - "bestTermName": "newTerm", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "newTerm" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "{{" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" + { + "annotation": null, + "segment": "Test" }, - "segment": "newTerm" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": " " }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" + { + "annotation": null, + "segment": "Doc" }, - "segment": "100" - } + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "}}" + } + ], + "tag": "UserObject" + }, + "termDocs": [ + [ + "aDoc", + "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + { + "contents": [ + { + "contents": "Test", + "tag": "Word" + }, + { + "contents": "Doc", + "tag": "Word" + } + ], + "tag": "Paragraph" + } + ] ], - "tag": "UserObject" + "termNames": [ + "aDoc" + ] }, - "termDocs": [], - "termNames": [ - "newTerm" - ] + "shortName": "aDoc" }, - "shortName": "newTerm" + "tag": "Removed" }, - "tag": "Added" + "tag": "Doc" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", - "newFullName": "renamedTerm", - "newShortName": "renamedTerm", - "oldNames": [ - "termRenameMe" - ], - "rendered": { - "bestTermName": "renamedTerm", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } + "contents": { + "aliasFullName": "aTermAlias", + "aliasShortName": "aTermAlias", + "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", + "otherNames": [ + "termAliasMe" ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "renamedTerm", - "tag": "HashQualifier" - }, - "segment": "renamedTerm" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "rendered": { + "bestTermName": "aTermAlias", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Nat", "tag": "TypeReference" }, "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "renamedTerm", - "tag": "HashQualifier" - }, - "segment": "renamedTerm" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" - }, - "segment": "3" } ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "renamedTerm" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "fullName": "termDeleteMe", - "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", - "rendered": { - "bestTermName": "termDeleteMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" - }, - "segment": "termDeleteMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" + }, + "segment": "aTermAlias" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "termDeleteMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" + { + "annotation": null, + "segment": "\n" }, - "segment": "2" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termDeleteMe" - ] - }, - "shortName": "termDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " - }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" + }, + "segment": "aTermAlias" }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "annotation": { + "tag": "BindingEquals" }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - } + "segment": " =" }, { - "diffTag": "both", - "elements": [ - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": null, + "segment": " " }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "annotation": { + "tag": "NumericLiteral" }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - } + "segment": "1" } ], "tag": "UserObject" }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termDependsOnUpdateMe", - "defnTermTag": "Plain", + "termDocs": [], + "termNames": [ + "aTermAlias", + "termAliasMe" + ] + } + }, + "tag": "Aliased" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "fullName": "aTest", + "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", + "rendered": { + "bestTermName": "aTest", + "defnTermTag": "Test", "signature": [ { "annotation": { - "contents": "##Text", + "tag": "DelimiterChar" + }, + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "]" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "aTest", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "aTest" }, { "annotation": { @@ -1928,10 +1418,22 @@ }, { "annotation": { - "contents": "##Text", + "tag": "DelimiterChar" + }, + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "]" }, { "annotation": null, @@ -1939,10 +1441,10 @@ }, { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "aTest", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "aTest" }, { "annotation": { @@ -1952,23 +1454,21 @@ }, { "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " + "segment": " " }, { "annotation": { - "tag": "UseKeyword" + "contents": "##Sequence", + "tag": "TypeReference" }, - "segment": "use " + "segment": "[" }, { "annotation": { - "tag": "UsePrefix" + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", + "tag": "TermReference" }, - "segment": "Text" + "segment": "Ok" }, { "annotation": null, @@ -1976,24 +1476,62 @@ }, { "annotation": { - "tag": "UseSuffix" + "tag": "TextLiteral" }, - "segment": "++" + "segment": "\"Done\"" }, { - "annotation": null, - "segment": "\n" + "annotation": { + "contents": "##Sequence", + "tag": "TypeReference" + }, + "segment": "]" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "aTest" + ] + }, + "shortName": "aTest" + }, + "tag": "Removed" + }, + "tag": "Test" + }, + { + "contents": { + "contents": { + "fullName": "newTerm", + "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", + "rendered": { + "bestTermName": "newTerm", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ { - "annotation": null, - "segment": " " + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" + }, + "segment": "newTerm" }, { "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "tag": "TypeAscriptionColon" }, - "segment": "termUpdateMe" + "segment": " :" }, { "annotation": null, @@ -2001,10 +1539,27 @@ }, { "annotation": { - "contents": "##Text.++", - "tag": "TermReference" + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" + }, + "segment": "newTerm" + }, + { + "annotation": { + "tag": "BindingEquals" }, - "segment": "++" + "segment": " =" }, { "annotation": null, @@ -2012,39 +1567,53 @@ }, { "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "tag": "NumericLiteral" }, - "segment": "termUpdateMe" + "segment": "100" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "termDependsOnUpdateMe" + "newTerm" ] }, - "right": { - "bestTermName": "termDependsOnUpdateMe", + "shortName": "newTerm" + }, + "tag": "Added" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", + "newFullName": "renamedTerm", + "newShortName": "renamedTerm", + "oldNames": [ + "termRenameMe" + ], + "rendered": { + "bestTermName": "renamedTerm", "defnTermTag": "Plain", "signature": [ { "annotation": { - "contents": "##Text", + "contents": "##Nat", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Nat" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "renamedTerm", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "renamedTerm" }, { "annotation": { @@ -2058,10 +1627,10 @@ }, { "annotation": { - "contents": "##Text", + "contents": "##Nat", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Nat" }, { "annotation": null, @@ -2069,10 +1638,10 @@ }, { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "renamedTerm", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "renamedTerm" }, { "annotation": { @@ -2082,23 +1651,58 @@ }, { "annotation": null, - "segment": "\n" + "segment": " " }, { - "annotation": null, - "segment": " " + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "3" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "renamedTerm" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "fullName": "termDeleteMe", + "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", + "rendered": { + "bestTermName": "termDeleteMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ { "annotation": { - "tag": "UseKeyword" + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - "segment": "use " + "segment": "termDeleteMe" }, { "annotation": { - "tag": "UsePrefix" + "tag": "TypeAscriptionColon" }, - "segment": "Text" + "segment": " :" }, { "annotation": null, @@ -2106,35 +1710,27 @@ }, { "annotation": { - "tag": "UseSuffix" + "contents": "##Nat", + "tag": "TypeReference" }, - "segment": "++" + "segment": "Nat" }, { "annotation": null, "segment": "\n" }, - { - "annotation": null, - "segment": " " - }, { "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - "segment": "termUpdateMe" - }, - { - "annotation": null, - "segment": " " + "segment": "termDeleteMe" }, { "annotation": { - "contents": "##Text.++", - "tag": "TermReference" + "tag": "BindingEquals" }, - "segment": "++" + "segment": " =" }, { "annotation": null, @@ -2142,554 +1738,961 @@ }, { "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + "tag": "NumericLiteral" }, - "segment": "termUpdateMe" + "segment": "2" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "termDependsOnUpdateMe" + "termDeleteMe" ] - } + }, + "shortName": "termDeleteMe" }, - "fullName": "termDependsOnUpdateMe", - "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", - "newTag": "Plain", - "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", - "oldTag": "Plain", - "shortName": "termDependsOnUpdateMe" + "tag": "Removed" }, - "tag": "Propagated" + "tag": "Plain" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "diff": { + "contents": { "diff": { "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" }, - "segment": " =" + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - { - "annotation": null, - "segment": " " + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + }, + { + "diffTag": "both", + "elements": [ + { + "annotation": null, + "segment": " " }, - "segment": "\"original\"" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" }, - "segment": "\"updated\"" + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" + }, + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" } - ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "termDependsOnUpdateMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" } ], - "tag": "UserObject" + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termDependsOnUpdateMe" + ] }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ + "right": { + "bestTermName": "termDependsOnUpdateMe", + "defnTermTag": "Plain", + "signature": [ { "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termDependsOnUpdateMe" + ] + } + }, + "fullName": "termDependsOnUpdateMe", + "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", + "newTag": "Plain", + "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", + "oldTag": "Plain", + "shortName": "termDependsOnUpdateMe" + }, + "tag": "Propagated" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + } + ] }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"original\"" + } + ] }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"updated\"" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"original\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - }, - "right": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": null, + "segment": "\n" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"original\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + }, + "right": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"updated\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - } + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"updated\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + } + }, + "fullName": "termUpdateMe", + "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "newTag": "Plain", + "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "oldTag": "Plain", + "shortName": "termUpdateMe" }, - "fullName": "termUpdateMe", - "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "newTag": "Plain", - "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "oldTag": "Plain", - "shortName": "termUpdateMe" + "tag": "Updated" }, - "tag": "Updated" - }, - "tag": "Plain" - } - ], - "children": [ - { - "contents": { - "changes": [], - "children": [ - { - "contents": { - "changes": [ - { - "contents": { + "tag": "Plain" + } + ], + "children": [ + { + "contents": { + "changes": [], + "children": [ + { + "contents": { + "changes": [ + { "contents": { - "fullName": "a.definition.at.path1", - "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", - "rendered": { - "bestTermName": "path1", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path1" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "contents": { + "fullName": "a.definition.at.path1", + "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", + "rendered": { + "bestTermName": "path1", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path1" }, - "segment": "a.definition.at.path1" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"definition at path\"" - } - ], - "tag": "UserObject" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path1" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"definition at path\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "a.definition.at.path1" + ] }, - "termDocs": [], - "termNames": [ - "a.definition.at.path1" - ] + "shortName": "path1" }, - "shortName": "path1" + "tag": "Removed" }, - "tag": "Removed" + "tag": "Plain" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "fullName": "a.definition.at.path2", - "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", - "rendered": { - "bestTermName": "path2", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path2" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "contents": { + "fullName": "a.definition.at.path2", + "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", + "rendered": { + "bestTermName": "path2", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path2" }, - "segment": "a.definition.at.path2" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"definition at path2\"" - } - ], - "tag": "UserObject" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path2" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"definition at path2\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "a.definition.at.path2" + ] }, - "termDocs": [], - "termNames": [ - "a.definition.at.path2" - ] + "shortName": "path2" }, - "shortName": "path2" + "tag": "Removed" }, - "tag": "Removed" - }, - "tag": "Plain" - } - ], - "children": [] + "tag": "Plain" + } + ], + "children": [] + }, + "path": "definition.at" }, - "path": "definition.at" - }, - { - "contents": { - "changes": [ - { - "contents": { + { + "contents": { + "changes": [ + { "contents": { - "fullName": "a.different.path", - "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", - "rendered": { - "bestTermName": "path", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" - }, - "segment": "a.different.path" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "contents": { + "fullName": "a.different.path", + "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", + "rendered": { + "bestTermName": "path", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" + }, + "segment": "a.different.path" }, - "segment": "a.different.path" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"definition at different path\"" - } - ], - "tag": "UserObject" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" + }, + "segment": "a.different.path" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"definition at different path\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "a.different.path" + ] }, - "termDocs": [], - "termNames": [ - "a.different.path" - ] + "shortName": "path" }, - "shortName": "path" + "tag": "Removed" }, - "tag": "Removed" - }, - "tag": "Plain" - } - ], - "children": [] - }, - "path": "different" - } - ] - }, - "path": "a" - } - ] + "tag": "Plain" + } + ], + "children": [] + }, + "path": "different" + } + ] + }, + "path": "a" + } + ] + }, + "libdeps": [] }, - "libdeps": [] + "diffKind": "ok" }, "newRef": "diff-end", "newRefHash": "#f2bjgi4tm53bf6dcfcukt5a6as3ktlrbiacnqq81nco8i4g7dg6pt14vmc1b7ulsb7rt683qjt2rvg9u92uo5mk1gaqgo8cl30umep8", diff --git a/transcripts/share-apis/contribution-diffs/namespace-diff.json b/transcripts/share-apis/contribution-diffs/namespace-diff.json index db781a63..b50d9313 100644 --- a/transcripts/share-apis/contribution-diffs/namespace-diff.json +++ b/transcripts/share-apis/contribution-diffs/namespace-diff.json @@ -1,615 +1,180 @@ { "body": { "diff": { - "defns": { - "changes": [ - { - "contents": { + "diff": { + "defns": { + "changes": [ + { "contents": { - "aliasFullName": "ATypeAlias", - "aliasShortName": "ATypeAlias", - "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", - "otherNames": [ - "DataAliasMe" - ], - "rendered": { - "bestTypeName": "ATypeAlias", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "ATypeAlias", - "tag": "HashQualifier" - }, - "segment": "ATypeAlias" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", - "tag": "TermReference" - }, - "segment": "B" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "ATypeAlias", + "contents": { + "aliasFullName": "ATypeAlias", + "aliasShortName": "ATypeAlias", + "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", + "otherNames": [ "DataAliasMe" - ] - } - }, - "tag": "Aliased" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "aliasFullName": "AbilityAlias", - "aliasShortName": "AbilityAlias", - "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "otherNames": [ - "AbilityAliasMe" - ], - "rendered": { - "bestTypeName": "AbilityAlias", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityAlias", - "tag": "HashQualifier" - }, - "segment": "AbilityAlias" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", - "tag": "TermReference" - }, - "segment": "abilityAliasMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "tag": "TypeReference" - }, - "segment": "AbilityAlias" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityAlias", - "AbilityAliasMe" - ] - } - }, - "tag": "Aliased" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "fullName": "AbilityDeleteMe", - "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", - "rendered": { - "bestTypeName": "AbilityDeleteMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityDeleteMe", - "tag": "HashQualifier" - }, - "segment": "AbilityDeleteMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", - "tag": "TermReference" - }, - "segment": "abilityDeleteMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", - "tag": "TypeReference" - }, - "segment": "AbilityDeleteMe" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityDeleteMe" - ] - }, - "shortName": "AbilityDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "fullName": "AbilityNew", - "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", - "rendered": { - "bestTypeName": "AbilityNew", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityNew", - "tag": "HashQualifier" - }, - "segment": "AbilityNew" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", - "tag": "TermReference" - }, - "segment": "abilityNew" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" + ], + "rendered": { + "bestTypeName": "ATypeAlias", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "segment": "{" - }, - { - "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "AbilityNew" - }, - { - "annotation": { - "tag": "AbilityBraces" + { + "annotation": { + "contents": "ATypeAlias", + "tag": "HashQualifier" + }, + "segment": "ATypeAlias" }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " }, - "segment": "Text" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityNew" - ] + { + "annotation": { + "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", + "tag": "TermReference" + }, + "segment": "B" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "ATypeAlias", + "DataAliasMe" + ] + } }, - "shortName": "AbilityNew" + "tag": "Aliased" }, - "tag": "Added" + "tag": "Data" }, - "tag": "Ability" - }, - { - "contents": { + { "contents": { - "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", - "newFullName": "AbilityRenamed", - "newShortName": "AbilityRenamed", - "oldNames": [ - "AbilityRenameMe" - ], - "rendered": { - "bestTypeName": "AbilityRenamed", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityRenamed", - "tag": "HashQualifier" - }, - "segment": "AbilityRenamed" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", - "tag": "TermReference" - }, - "segment": "abilityRenameMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" + "contents": { + "aliasFullName": "AbilityAlias", + "aliasShortName": "AbilityAlias", + "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", + "otherNames": [ + "AbilityAliasMe" + ], + "rendered": { + "bestTypeName": "AbilityAlias", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" }, - "segment": "{" - }, - { - "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "AbilityRenamed" - }, - { - "annotation": { - "tag": "AbilityBraces" + { + "annotation": { + "contents": "AbilityAlias", + "tag": "HashQualifier" + }, + "segment": "AbilityAlias" }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityRenamed" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": null, + "segment": " " }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", "tag": "TermReference" }, - "segment": "abilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", - "tag": "TermReference" - } + "segment": "abilityAliasMe" }, { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - } - ] + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "tag": "TypeReference" + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - "segment": "AbilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "segment": "{" + }, + { + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", "tag": "TypeReference" - } + }, + "segment": "AbilityAlias" }, { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" }, { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] + "annotation": null, + "segment": " " }, { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ] + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" } ], "tag": "UserObject" }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "AbilityUpdateMe", + "typeDocs": [], + "typeNames": [ + "AbilityAlias", + "AbilityAliasMe" + ] + } + }, + "tag": "Aliased" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityDeleteMe", + "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "rendered": { + "bestTypeName": "AbilityDeleteMe", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -625,10 +190,10 @@ }, { "annotation": { - "contents": "AbilityUpdateMe", + "contents": "AbilityDeleteMe", "tag": "HashQualifier" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityDeleteMe" }, { "annotation": { @@ -646,10 +211,10 @@ }, { "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", "tag": "TermReference" }, - "segment": "abilityUpdateMe" + "segment": "abilityDeleteMe" }, { "annotation": { @@ -669,10 +234,10 @@ }, { "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", "tag": "TypeReference" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityDeleteMe" }, { "annotation": { @@ -696,11 +261,22 @@ }, "typeDocs": [], "typeNames": [ - "AbilityUpdateMe" + "AbilityDeleteMe" ] }, - "right": { - "bestTypeName": "AbilityUpdateMe", + "shortName": "AbilityDeleteMe" + }, + "tag": "Removed" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityNew", + "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "rendered": { + "bestTypeName": "AbilityNew", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -716,10 +292,10 @@ }, { "annotation": { - "contents": "AbilityUpdateMe", + "contents": "AbilityNew", "tag": "HashQualifier" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityNew" }, { "annotation": { @@ -737,10 +313,10 @@ }, { "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", "tag": "TermReference" }, - "segment": "abilityUpdateMe" + "segment": "abilityNew" }, { "annotation": { @@ -760,10 +336,10 @@ }, { "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", "tag": "TypeReference" }, - "segment": "AbilityUpdateMe" + "segment": "AbilityNew" }, { "annotation": { @@ -787,195 +363,453 @@ }, "typeDocs": [], "typeNames": [ - "AbilityUpdateMe" + "AbilityNew" ] - } + }, + "shortName": "AbilityNew" }, - "fullName": "AbilityUpdateMe", - "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "newTag": "Ability", - "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "oldTag": "Ability", - "shortName": "AbilityUpdateMe" + "tag": "Added" }, - "tag": "Updated" + "tag": "Ability" }, - "tag": "Ability" - }, - { - "contents": { + { "contents": { - "fullName": "DataDeleteMe", - "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", - "rendered": { - "bestTypeName": "DataDeleteMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" + "contents": { + "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "newFullName": "AbilityRenamed", + "newShortName": "AbilityRenamed", + "oldNames": [ + "AbilityRenameMe" + ], + "rendered": { + "bestTypeName": "AbilityRenamed", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataDeleteMe", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "DataDeleteMe" - }, - { - "annotation": { - "tag": "DelimiterChar" + { + "annotation": { + "contents": "AbilityRenamed", + "tag": "HashQualifier" + }, + "segment": "AbilityRenamed" }, - "segment": " = " - }, - { - "annotation": { - "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", - "tag": "TermReference" + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" }, - "segment": "C" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataDeleteMe" - ] + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", + "tag": "TermReference" + }, + "segment": "abilityRenameMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "tag": "TypeReference" + }, + "segment": "AbilityRenamed" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityRenamed" + ] + } }, - "shortName": "DataDeleteMe" + "tag": "RenamedFrom" }, - "tag": "Removed" + "tag": "Ability" }, - "tag": "Data" - }, - { - "contents": { + { "contents": { - "diff": { + "contents": { "diff": { "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "tag": "TermReference" + }, + "segment": "abilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "tag": "TermReference" + } + }, + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "tag": "TypeReference" + }, + "segment": "AbilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "tag": "TypeReference" + } + }, + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" }, - "segment": "type" + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTypeName": "AbilityUpdateMe", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", + "tag": "TermReference" + }, + "segment": "abilityUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "tag": "TypeReference" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityUpdateMe" + ] + }, + "right": { + "bestTypeName": "AbilityUpdateMe", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "tag": "TermReference" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" - }, - "segment": "D" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", - "tag": "TermReference" - }, - "segment": "D2" + "segment": "abilityUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "DataUpdateMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" + "segment": "{" }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" + { + "annotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "tag": "TypeReference" + }, + "segment": "AbilityUpdateMe" }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" }, - "segment": " = " - }, - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" + { + "annotation": null, + "segment": " " }, - "segment": "D" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataUpdateMe" - ] + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityUpdateMe" + ] + } }, - "right": { - "bestTypeName": "DataUpdateMe", + "fullName": "AbilityUpdateMe", + "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "newTag": "Ability", + "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "oldTag": "Ability", + "shortName": "AbilityUpdateMe" + }, + "tag": "Updated" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "DataDeleteMe", + "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", + "rendered": { + "bestTypeName": "DataDeleteMe", "defnTypeTag": "Data", "typeDefinition": { "contents": [ @@ -991,10 +825,10 @@ }, { "annotation": { - "contents": "DataUpdateMe", + "contents": "DataDeleteMe", "tag": "HashQualifier" }, - "segment": "DataUpdateMe" + "segment": "DataDeleteMe" }, { "annotation": { @@ -1004,917 +838,573 @@ }, { "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", "tag": "TermReference" }, - "segment": "D2" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" + "segment": "C" } ], "tag": "UserObject" }, "typeDocs": [], "typeNames": [ - "DataUpdateMe" + "DataDeleteMe" ] - } - }, - "fullName": "DataUpdateMe", - "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", - "newTag": "Data", - "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", - "oldTag": "Data", - "shortName": "DataUpdateMe" - }, - "tag": "Updated" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "fullName": "NewType", - "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", - "rendered": { - "bestTypeName": "NewType", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "NewType", - "tag": "HashQualifier" - }, - "segment": "NewType" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", - "tag": "TermReference" - }, - "segment": "X" - } - ], - "tag": "UserObject" }, - "typeDocs": [], - "typeNames": [ - "NewType" - ] + "shortName": "DataDeleteMe" }, - "shortName": "NewType" + "tag": "Removed" }, - "tag": "Added" + "tag": "Data" }, - "tag": "Data" - }, - { - "contents": { + { "contents": { - "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", - "newFullName": "RenamedType", - "newShortName": "RenamedType", - "oldNames": [ - "DataRenameMe" - ], - "rendered": { - "bestTypeName": "RenamedType", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", + "tag": "TermReference" + }, + "segment": "D" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] + } + ], + "tag": "UserObject" }, - { - "annotation": { - "contents": "RenamedType", - "tag": "HashQualifier" - }, - "segment": "RenamedType" + "diffKind": "diff" + }, + "left": { + "bestTypeName": "DataUpdateMe", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", + "tag": "TermReference" + }, + "segment": "D" + } + ], + "tag": "UserObject" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " + "typeDocs": [], + "typeNames": [ + "DataUpdateMe" + ] + }, + "right": { + "bestTypeName": "DataUpdateMe", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" }, - { - "annotation": { - "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", - "tag": "TermReference" - }, - "segment": "E" - } - ], - "tag": "UserObject" + "typeDocs": [], + "typeNames": [ + "DataUpdateMe" + ] + } }, - "typeDocs": [], - "typeNames": [ - "RenamedType" - ] - } + "fullName": "DataUpdateMe", + "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", + "newTag": "Data", + "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", + "oldTag": "Data", + "shortName": "DataUpdateMe" + }, + "tag": "Updated" }, - "tag": "RenamedFrom" + "tag": "Data" }, - "tag": "Data" - }, - { - "contents": { + { "contents": { - "fullName": "aDoc", - "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - "rendered": { - "bestTermName": "aDoc", - "defnTermTag": "Doc", - "signature": [ - { - "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" - }, - "segment": "Doc2" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" - }, - "segment": "aDoc" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" - }, - "segment": "Doc2" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" + "contents": { + "fullName": "NewType", + "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", + "rendered": { + "bestTypeName": "NewType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "segment": "aDoc" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": " " }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "DocDelimiter" + { + "annotation": { + "contents": "NewType", + "tag": "HashQualifier" + }, + "segment": "NewType" }, - "segment": "{{" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": null, - "segment": "Test" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": null, - "segment": "Doc" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "DocDelimiter" + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " }, - "segment": "}}" - } - ], - "tag": "UserObject" - }, - "termDocs": [ - [ - "aDoc", - "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - { - "contents": [ - { - "contents": "Test", - "tag": "Word" + { + "annotation": { + "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", + "tag": "TermReference" }, - { - "contents": "Doc", - "tag": "Word" - } - ], - "tag": "Paragraph" - } + "segment": "X" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "NewType" ] - ], - "termNames": [ - "aDoc" - ] + }, + "shortName": "NewType" }, - "shortName": "aDoc" + "tag": "Added" }, - "tag": "Removed" + "tag": "Data" }, - "tag": "Doc" - }, - { - "contents": { + { "contents": { - "aliasFullName": "aTermAlias", - "aliasShortName": "aTermAlias", - "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", - "otherNames": [ - "termAliasMe" - ], - "rendered": { - "bestTermName": "aTermAlias", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } + "contents": { + "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", + "newFullName": "RenamedType", + "newShortName": "RenamedType", + "oldNames": [ + "DataRenameMe" ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" - }, - "segment": "aTermAlias" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "rendered": { + "bestTypeName": "RenamedType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "aTermAlias" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "contents": "RenamedType", + "tag": "HashQualifier" + }, + "segment": "RenamedType" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " }, - "segment": "1" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "aTermAlias", - "termAliasMe" - ] - } + { + "annotation": { + "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", + "tag": "TermReference" + }, + "segment": "E" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "RenamedType" + ] + } + }, + "tag": "RenamedFrom" }, - "tag": "Aliased" + "tag": "Data" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "fullName": "aTest", - "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", - "rendered": { - "bestTermName": "aTest", - "defnTermTag": "Test", - "signature": [ - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", - "tag": "TypeReference" - }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "]" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aTest", - "tag": "HashQualifier" - }, - "segment": "aTest" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, + "contents": { + "fullName": "aDoc", + "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + "rendered": { + "bestTermName": "aDoc", + "defnTermTag": "Doc", + "signature": [ { "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", "tag": "TypeReference" }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" + "segment": "Doc2" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" }, - "segment": "]" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "aTest", - "tag": "HashQualifier" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": "aTest" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": " " }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" + { + "annotation": { + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", + "tag": "TypeReference" + }, + "segment": "Doc2" }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", - "tag": "TermReference" + { + "annotation": null, + "segment": "\n" }, - "segment": "Ok" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" }, - "segment": "\"Done\"" - }, - { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" }, - "segment": "]" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "aTest" - ] - }, - "shortName": "aTest" - }, - "tag": "Removed" - }, - "tag": "Test" - }, - { - "contents": { - "contents": { - "fullName": "newTerm", - "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", - "rendered": { - "bestTermName": "newTerm", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "newTerm" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "{{" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" + { + "annotation": null, + "segment": "Test" }, - "segment": "newTerm" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": " " }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" + { + "annotation": null, + "segment": "Doc" }, - "segment": "100" - } + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "}}" + } + ], + "tag": "UserObject" + }, + "termDocs": [ + [ + "aDoc", + "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + { + "contents": [ + { + "contents": "Test", + "tag": "Word" + }, + { + "contents": "Doc", + "tag": "Word" + } + ], + "tag": "Paragraph" + } + ] ], - "tag": "UserObject" + "termNames": [ + "aDoc" + ] }, - "termDocs": [], - "termNames": [ - "newTerm" - ] + "shortName": "aDoc" }, - "shortName": "newTerm" + "tag": "Removed" }, - "tag": "Added" + "tag": "Doc" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", - "newFullName": "renamedTerm", - "newShortName": "renamedTerm", - "oldNames": [ - "termRenameMe" - ], - "rendered": { - "bestTermName": "renamedTerm", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } + "contents": { + "aliasFullName": "aTermAlias", + "aliasShortName": "aTermAlias", + "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", + "otherNames": [ + "termAliasMe" ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "renamedTerm", - "tag": "HashQualifier" - }, - "segment": "renamedTerm" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "rendered": { + "bestTermName": "aTermAlias", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Nat", "tag": "TypeReference" }, "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "renamedTerm", - "tag": "HashQualifier" - }, - "segment": "renamedTerm" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" - }, - "segment": "3" } ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "renamedTerm" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "fullName": "termDeleteMe", - "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", - "rendered": { - "bestTermName": "termDeleteMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" - }, - "segment": "termDeleteMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" + }, + "segment": "aTermAlias" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": "Nat" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "termDeleteMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "NumericLiteral" + { + "annotation": null, + "segment": "\n" }, - "segment": "2" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termDeleteMe" - ] - }, - "shortName": "termDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " - }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" + }, + "segment": "aTermAlias" }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "annotation": { + "tag": "BindingEquals" }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - } + "segment": " =" }, { - "diffTag": "both", - "elements": [ - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": " " - } - ] + "annotation": null, + "segment": " " }, { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "annotation": { + "tag": "NumericLiteral" }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - } + "segment": "1" } ], "tag": "UserObject" }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termDependsOnUpdateMe", - "defnTermTag": "Plain", + "termDocs": [], + "termNames": [ + "aTermAlias", + "termAliasMe" + ] + } + }, + "tag": "Aliased" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "fullName": "aTest", + "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", + "rendered": { + "bestTermName": "aTest", + "defnTermTag": "Test", "signature": [ { "annotation": { - "contents": "##Text", + "tag": "DelimiterChar" + }, + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "]" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "aTest", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "aTest" }, { "annotation": { @@ -1928,10 +1418,22 @@ }, { "annotation": { - "contents": "##Text", + "tag": "DelimiterChar" + }, + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "]" }, { "annotation": null, @@ -1939,10 +1441,10 @@ }, { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "aTest", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "aTest" }, { "annotation": { @@ -1952,23 +1454,21 @@ }, { "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " + "segment": " " }, { "annotation": { - "tag": "UseKeyword" + "contents": "##Sequence", + "tag": "TypeReference" }, - "segment": "use " + "segment": "[" }, { "annotation": { - "tag": "UsePrefix" + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", + "tag": "TermReference" }, - "segment": "Text" + "segment": "Ok" }, { "annotation": null, @@ -1976,24 +1476,62 @@ }, { "annotation": { - "tag": "UseSuffix" + "tag": "TextLiteral" }, - "segment": "++" + "segment": "\"Done\"" }, { - "annotation": null, - "segment": "\n" + "annotation": { + "contents": "##Sequence", + "tag": "TypeReference" + }, + "segment": "]" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "aTest" + ] + }, + "shortName": "aTest" + }, + "tag": "Removed" + }, + "tag": "Test" + }, + { + "contents": { + "contents": { + "fullName": "newTerm", + "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", + "rendered": { + "bestTermName": "newTerm", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ { - "annotation": null, - "segment": " " + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" + }, + "segment": "newTerm" }, { "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "tag": "TypeAscriptionColon" }, - "segment": "termUpdateMe" + "segment": " :" }, { "annotation": null, @@ -2001,10 +1539,27 @@ }, { "annotation": { - "contents": "##Text.++", - "tag": "TermReference" + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" + }, + "segment": "newTerm" + }, + { + "annotation": { + "tag": "BindingEquals" }, - "segment": "++" + "segment": " =" }, { "annotation": null, @@ -2012,39 +1567,53 @@ }, { "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "tag": "NumericLiteral" }, - "segment": "termUpdateMe" + "segment": "100" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "termDependsOnUpdateMe" + "newTerm" ] }, - "right": { - "bestTermName": "termDependsOnUpdateMe", + "shortName": "newTerm" + }, + "tag": "Added" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", + "newFullName": "renamedTerm", + "newShortName": "renamedTerm", + "oldNames": [ + "termRenameMe" + ], + "rendered": { + "bestTermName": "renamedTerm", "defnTermTag": "Plain", "signature": [ { "annotation": { - "contents": "##Text", + "contents": "##Nat", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Nat" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "renamedTerm", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "renamedTerm" }, { "annotation": { @@ -2058,10 +1627,10 @@ }, { "annotation": { - "contents": "##Text", + "contents": "##Nat", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Nat" }, { "annotation": null, @@ -2069,10 +1638,10 @@ }, { "annotation": { - "contents": "termDependsOnUpdateMe", + "contents": "renamedTerm", "tag": "HashQualifier" }, - "segment": "termDependsOnUpdateMe" + "segment": "renamedTerm" }, { "annotation": { @@ -2082,23 +1651,58 @@ }, { "annotation": null, - "segment": "\n" + "segment": " " }, { - "annotation": null, - "segment": " " + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "3" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "renamedTerm" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "fullName": "termDeleteMe", + "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", + "rendered": { + "bestTermName": "termDeleteMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ { "annotation": { - "tag": "UseKeyword" + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - "segment": "use " + "segment": "termDeleteMe" }, { "annotation": { - "tag": "UsePrefix" + "tag": "TypeAscriptionColon" }, - "segment": "Text" + "segment": " :" }, { "annotation": null, @@ -2106,35 +1710,27 @@ }, { "annotation": { - "tag": "UseSuffix" + "contents": "##Nat", + "tag": "TypeReference" }, - "segment": "++" + "segment": "Nat" }, { "annotation": null, "segment": "\n" }, - { - "annotation": null, - "segment": " " - }, { "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - "segment": "termUpdateMe" - }, - { - "annotation": null, - "segment": " " + "segment": "termDeleteMe" }, { "annotation": { - "contents": "##Text.++", - "tag": "TermReference" + "tag": "BindingEquals" }, - "segment": "++" + "segment": " =" }, { "annotation": null, @@ -2142,554 +1738,961 @@ }, { "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + "tag": "NumericLiteral" }, - "segment": "termUpdateMe" + "segment": "2" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "termDependsOnUpdateMe" + "termDeleteMe" ] - } + }, + "shortName": "termDeleteMe" }, - "fullName": "termDependsOnUpdateMe", - "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", - "newTag": "Plain", - "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", - "oldTag": "Plain", - "shortName": "termDependsOnUpdateMe" + "tag": "Removed" }, - "tag": "Propagated" + "tag": "Plain" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "diff": { + "contents": { "diff": { "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" + { + "annotation": null, + "segment": " " }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" }, - "segment": " =" + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - { - "annotation": null, - "segment": " " + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + }, + { + "diffTag": "both", + "elements": [ + { + "annotation": null, + "segment": " " }, - "segment": "\"original\"" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" }, - "segment": "\"updated\"" + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" + }, + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" } - ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "termDependsOnUpdateMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" } ], - "tag": "UserObject" + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termDependsOnUpdateMe" + ] }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ + "right": { + "bestTermName": "termDependsOnUpdateMe", + "defnTermTag": "Plain", + "signature": [ { "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + }, + "segment": "termUpdateMe" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termDependsOnUpdateMe" + ] + } + }, + "fullName": "termDependsOnUpdateMe", + "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", + "newTag": "Plain", + "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", + "oldTag": "Plain", + "shortName": "termDependsOnUpdateMe" + }, + "tag": "Propagated" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + } + ] }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"original\"" + } + ] }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"updated\"" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"original\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - }, - "right": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": null, + "segment": "\n" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"original\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + }, + "right": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"updated\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - } + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"updated\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + } + }, + "fullName": "termUpdateMe", + "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "newTag": "Plain", + "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "oldTag": "Plain", + "shortName": "termUpdateMe" }, - "fullName": "termUpdateMe", - "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "newTag": "Plain", - "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "oldTag": "Plain", - "shortName": "termUpdateMe" + "tag": "Updated" }, - "tag": "Updated" - }, - "tag": "Plain" - } - ], - "children": [ - { - "contents": { - "changes": [], - "children": [ - { - "contents": { - "changes": [ - { - "contents": { + "tag": "Plain" + } + ], + "children": [ + { + "contents": { + "changes": [], + "children": [ + { + "contents": { + "changes": [ + { "contents": { - "fullName": "a.definition.at.path1", - "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", - "rendered": { - "bestTermName": "path1", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path1" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "contents": { + "fullName": "a.definition.at.path1", + "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", + "rendered": { + "bestTermName": "path1", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path1" }, - "segment": "a.definition.at.path1" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"definition at path\"" - } - ], - "tag": "UserObject" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path1" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"definition at path\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "a.definition.at.path1" + ] }, - "termDocs": [], - "termNames": [ - "a.definition.at.path1" - ] + "shortName": "path1" }, - "shortName": "path1" + "tag": "Removed" }, - "tag": "Removed" + "tag": "Plain" }, - "tag": "Plain" - }, - { - "contents": { + { "contents": { - "fullName": "a.definition.at.path2", - "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", - "rendered": { - "bestTermName": "path2", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path2" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "contents": { + "fullName": "a.definition.at.path2", + "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", + "rendered": { + "bestTermName": "path2", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path2" }, - "segment": "a.definition.at.path2" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"definition at path2\"" - } - ], - "tag": "UserObject" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path2" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"definition at path2\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "a.definition.at.path2" + ] }, - "termDocs": [], - "termNames": [ - "a.definition.at.path2" - ] + "shortName": "path2" }, - "shortName": "path2" + "tag": "Removed" }, - "tag": "Removed" - }, - "tag": "Plain" - } - ], - "children": [] + "tag": "Plain" + } + ], + "children": [] + }, + "path": "definition.at" }, - "path": "definition.at" - }, - { - "contents": { - "changes": [ - { - "contents": { + { + "contents": { + "changes": [ + { "contents": { - "fullName": "a.different.path", - "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", - "rendered": { - "bestTermName": "path", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" - }, - "segment": "a.different.path" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + "contents": { + "fullName": "a.different.path", + "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", + "rendered": { + "bestTermName": "path", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" + }, + "segment": "a.different.path" }, - "segment": "a.different.path" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"definition at different path\"" - } - ], - "tag": "UserObject" + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" + }, + "segment": "a.different.path" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"definition at different path\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "a.different.path" + ] }, - "termDocs": [], - "termNames": [ - "a.different.path" - ] + "shortName": "path" }, - "shortName": "path" + "tag": "Removed" }, - "tag": "Removed" - }, - "tag": "Plain" - } - ], - "children": [] - }, - "path": "different" - } - ] - }, - "path": "a" - } - ] + "tag": "Plain" + } + ], + "children": [] + }, + "path": "different" + } + ] + }, + "path": "a" + } + ] + }, + "libdeps": [] }, - "libdeps": [] + "diffKind": "ok" }, "newRef": "diff-end", "newRefHash": "#f2bjgi4tm53bf6dcfcukt5a6as3ktlrbiacnqq81nco8i4g7dg6pt14vmc1b7ulsb7rt683qjt2rvg9u92uo5mk1gaqgo8cl30umep8", diff --git a/transcripts/share-apis/contributions/merged-contribution-diff.json b/transcripts/share-apis/contributions/merged-contribution-diff.json index c0422147..12eb1d5a 100644 --- a/transcripts/share-apis/contributions/merged-contribution-diff.json +++ b/transcripts/share-apis/contributions/merged-contribution-diff.json @@ -1,254 +1,257 @@ { "body": { "diff": { - "defns": { - "changes": [ - { - "contents": { + "diff": { + "defns": { + "changes": [ + { "contents": { - "diff": { + "contents": { "diff": { "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" }, - "segment": "term" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": "\n" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "\"start\"" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" }, - "segment": "\"feature-one\"" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " + } + ] }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"start\"" + } + ] }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"feature-one\"" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "term" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"start\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - }, - "right": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": null, + "segment": "\n" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"start\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + }, + "right": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "term" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"feature-one\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - } + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"feature-one\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + } + }, + "fullName": "term", + "newHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", + "newTag": "Plain", + "oldHash": "#rhaja5f1cv52a3h2sook0mnagjn62dvm0e66auh1o741bn1qc0fefjlsqqc8mgar0nlui5fdia8ji7j3fbpejdv4dgb3vlh6bq4q4b8", + "oldTag": "Plain", + "shortName": "term" }, - "fullName": "term", - "newHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", - "newTag": "Plain", - "oldHash": "#rhaja5f1cv52a3h2sook0mnagjn62dvm0e66auh1o741bn1qc0fefjlsqqc8mgar0nlui5fdia8ji7j3fbpejdv4dgb3vlh6bq4q4b8", - "oldTag": "Plain", - "shortName": "term" + "tag": "Updated" }, - "tag": "Updated" - }, - "tag": "Plain" - } - ], - "children": [] + "tag": "Plain" + } + ], + "children": [] + }, + "libdeps": [] }, - "libdeps": [] + "diffKind": "ok" }, "newRef": "feature-one", "newRefHash": "#7shvkj0gn9mfne1pemp3oudmo23vio4d8ualvbah6avr7m5471rssu9cd4o6i4pn91bgc62vgnm0oper0itgtmopqmff7c0b40ui1s0", diff --git a/transcripts/share-apis/contributions/run.zsh b/transcripts/share-apis/contributions/run.zsh index 789fc539..39880fb5 100755 --- a/transcripts/share-apis/contributions/run.zsh +++ b/transcripts/share-apis/contributions/run.zsh @@ -118,6 +118,17 @@ transcript_ucm transcript merge-contribution-branches.md # Fetch the contribution to see that it's been marked as merged. fetch "$transcript_user" GET merged-contribution '/users/transcripts/projects/bca-updates/contributions/1' +# Hacky, but since namespace diffs are computed asynchronously, we just block here until there are 5 (the number this +# test creates). Don't wait more than 10 seconds, just in case. +expectedNumberOfNamespaceDiffs=5 +for i in {1..5}; do + if [[ $(pg_sql "select count(*) from namespace_diffs;") -lt $expectedNumberOfNamespaceDiffs ]]; then + sleep 1 + else + break + fi +done + # BCA of contribution diff should still be frozen at it's pre-merge hash. The bca and source hash should be different (or else we'd see no diff!) fetch "$transcript_user" GET merged-contribution-diff '/users/transcripts/projects/bca-updates/contributions/1/diff' diff --git a/transcripts/share-apis/contributions/transitive-contribution-diff.json b/transcripts/share-apis/contributions/transitive-contribution-diff.json index e96edaba..98aa28de 100644 --- a/transcripts/share-apis/contributions/transitive-contribution-diff.json +++ b/transcripts/share-apis/contributions/transitive-contribution-diff.json @@ -1,254 +1,257 @@ { "body": { "diff": { - "defns": { - "changes": [ - { - "contents": { + "diff": { + "defns": { + "changes": [ + { "contents": { - "diff": { + "contents": { "diff": { "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " }, - "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" }, - "segment": "term" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": null, + "segment": "\n" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "\"feature-one\"" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" }, - "segment": "\"feature-two\"" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + { + "annotation": null, + "segment": " " + } + ] }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"feature-one\"" + } + ] }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"feature-two\"" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "term" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"feature-one\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - }, - "right": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" + { + "annotation": null, + "segment": "\n" }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"feature-one\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + }, + "right": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" }, - "segment": "term" - }, - { - "annotation": { - "tag": "BindingEquals" + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "TextLiteral" + { + "annotation": null, + "segment": " " }, - "segment": "\"feature-two\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - } + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" + }, + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"feature-two\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + } + }, + "fullName": "term", + "newHash": "#918iukm79ii0jll0m3qtsrcqjp1sqe5rdpf1kochqp52a52s9ciil7mu6m3t4l39pdk60imhj5be1d9rat2lgdmr6u0jn93v7v8o6rg", + "newTag": "Plain", + "oldHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", + "oldTag": "Plain", + "shortName": "term" }, - "fullName": "term", - "newHash": "#918iukm79ii0jll0m3qtsrcqjp1sqe5rdpf1kochqp52a52s9ciil7mu6m3t4l39pdk60imhj5be1d9rat2lgdmr6u0jn93v7v8o6rg", - "newTag": "Plain", - "oldHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", - "oldTag": "Plain", - "shortName": "term" + "tag": "Updated" }, - "tag": "Updated" - }, - "tag": "Plain" - } - ], - "children": [] + "tag": "Plain" + } + ], + "children": [] + }, + "libdeps": [] }, - "libdeps": [] + "diffKind": "ok" }, "newRef": "feature-two", "newRefHash": "#ktjspqi8s5ngg129a6lt7i9kd488isfoq8hqmsv54f327de28dq9u0n1dp1vlbgs8jdc6bqss3h46ep9241405ml19nr0gekel56pig", From e0dee5e232428979f1c7020fd49cfbe9852f9dfd Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Thu, 24 Apr 2025 14:55:34 -0400 Subject: [PATCH 07/16] ping background worker in contribution diffs endpoint --- src/Share/BackgroundJobs/Diffs/Queries.hs | 19 ++++++++++++++++--- src/Share/Postgres/Contributions/Queries.hs | 2 +- src/Share/Web/Share/Contributions/Impl.hs | 4 ++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/Queries.hs b/src/Share/BackgroundJobs/Diffs/Queries.hs index a8cace3e..a3b965bf 100644 --- a/src/Share/BackgroundJobs/Diffs/Queries.hs +++ b/src/Share/BackgroundJobs/Diffs/Queries.hs @@ -1,14 +1,27 @@ module Share.BackgroundJobs.Diffs.Queries - ( submitContributionsToBeDiffed, + ( submitContributionToBeDiffed, + submitContributionsToBeDiffed, claimContributionToDiff, ) where -import Data.Foldable (toList) -import Data.Set (Set) import Share.IDs import Share.Postgres import Share.Postgres.Notifications qualified as Notif +import Unison.Prelude + +submitContributionToBeDiffed :: (QueryM m) => ContributionId -> m () +submitContributionToBeDiffed contributionId = do + result <- + query1Col @Int64 + [sql| + INSERT INTO contribution_diff_queue (contribution_id) + VALUES (#{contributionId}) + ON CONFLICT DO NOTHING + RETURNING 1 + |] + whenJust result \_ -> + Notif.notifyChannel Notif.ContributionDiffChannel submitContributionsToBeDiffed :: (QueryM m) => Set ContributionId -> m () submitContributionsToBeDiffed contributions = do diff --git a/src/Share/Postgres/Contributions/Queries.hs b/src/Share/Postgres/Contributions/Queries.hs index 732e39a0..9185cd74 100644 --- a/src/Share/Postgres/Contributions/Queries.hs +++ b/src/Share/Postgres/Contributions/Queries.hs @@ -564,7 +564,7 @@ getPrecomputedNamespaceDiff :: m (Maybe Text) getPrecomputedNamespaceDiff (CodebaseEnv {codebaseOwner = leftCodebaseUser}, leftCausalId) - (CodebaseEnv {codebaseOwner = rightCodebaseUser}, rightCausalId) = do + (CodebaseEnv {codebaseOwner = rightCodebaseUser}, rightCausalId) = PG.query1Col @Text [PG.sql| SELECT (diff :: text) diff --git a/src/Share/Web/Share/Contributions/Impl.hs b/src/Share/Web/Share/Contributions/Impl.hs index d474f0d8..3d52e352 100644 --- a/src/Share/Web/Share/Contributions/Impl.hs +++ b/src/Share/Web/Share/Contributions/Impl.hs @@ -290,6 +290,10 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr <$> CausalQ.expectCausalHashesByIdsOf id oldBranchCausalId <*> CausalQ.expectCausalHashesByIdsOf id newBranchCausalId <*> ContributionsQ.getPrecomputedNamespaceDiff (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) + -- If the diff hasn't been computed by a background worker yet, signal interest in it (perhaps redundantly), in case + -- it had been picked up by a worker that then went on to crash before completing and storing the diff. + when (isNothing maybeNamespaceDiff) do + PG.runTransaction (DiffsQ.submitContributionToBeDiffed contributionId) let response = ShareNamespaceDiffResponse { project = projectShorthand, From f87012e9fb02b1ed25ae4cf4b7096be64c0fd52a Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Mon, 28 Apr 2025 09:41:15 -0400 Subject: [PATCH 08/16] flatten json --- src/Share/Web/Share/Diffs/Types.hs | 192 +- .../contribution-diffs/contribution-diff.json | 4168 ++++++++--------- .../contribution-diffs/namespace-diff.json | 4168 ++++++++--------- .../merged-contribution-diff.json | 430 +- .../transitive-contribution-diff.json | 430 +- 5 files changed, 4720 insertions(+), 4668 deletions(-) diff --git a/src/Share/Web/Share/Diffs/Types.hs b/src/Share/Web/Share/Diffs/Types.hs index 0d532a88..c3ddf5e4 100644 --- a/src/Share/Web/Share/Diffs/Types.hs +++ b/src/Share/Web/Share/Diffs/Types.hs @@ -22,64 +22,64 @@ data ShareNamespaceDiffStatus | ShareNamespaceDiffStatus'Error NamespaceDiffError | ShareNamespaceDiffStatus'StillComputing -instance ToJSON ShareNamespaceDiffStatus where - toJSON = \case - ShareNamespaceDiffStatus'Ok diff -> - object - [ "diff" .= diff, - "diffKind" .= ("ok" :: Text) - ] - ShareNamespaceDiffStatus'Error err -> - object - [ "diffKind" .= ("error" :: Text), - "error" - .= case err of - NamespaceDiffs.ImpossibleError _ -> - object - [ "errorKind" .= ("impossibleError" :: Text) - ] - NamespaceDiffs.IncoherentDecl reason -> - let f :: Text -> IncoherentDeclReason -> Value - f which reason = - object - ( "oldOrNewBranch" .= which - : case reason of - IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> - [ "errorKind" .= ("constructorAlias" :: Text), - "typeName" .= typeName, - "constructorName1" .= constructorName1, - "constructorName2" .= constructorName2 - ] - IncoherentDeclReason'MissingConstructorName typeName -> - [ "errorKind" .= ("missingConstructorName" :: Text), - "typeName" .= typeName - ] - IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> - [ "errorKind" .= ("constructorAlias" :: Text), - "constructorName1" .= constructorName1, - "constructorName2" .= constructorName2 - ] - IncoherentDeclReason'StrayConstructor _ constructorName -> - [ "errorKind" .= ("strayConstructor" :: Text), - "constructorName" .= constructorName - ] - ) - in case reason of - EitherWay.Alice reason -> f "old" reason - EitherWay.Bob reason -> f "new" reason - NamespaceDiffs.LibFoundAtUnexpectedPath _ -> - object - [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) - ] - NamespaceDiffs.MissingEntityError _ -> - object - [ "errorKind" .= ("missingEntityError" :: Text) - ] - ] - ShareNamespaceDiffStatus'StillComputing -> - object - [ "diffKind" .= ("computing" :: Text) - ] +-- instance ToJSON ShareNamespaceDiffStatus where +-- toJSON = \case +-- ShareNamespaceDiffStatus'Ok diff -> +-- object +-- [ "diff" .= diff, +-- "diffKind" .= ("ok" :: Text) +-- ] +-- ShareNamespaceDiffStatus'Error err -> +-- object +-- [ "diffKind" .= ("error" :: Text), +-- "error" +-- .= case err of +-- NamespaceDiffs.ImpossibleError _ -> +-- object +-- [ "errorKind" .= ("impossibleError" :: Text) +-- ] +-- NamespaceDiffs.IncoherentDecl reason -> +-- let f :: Text -> IncoherentDeclReason -> Value +-- f which reason = +-- object +-- ( "oldOrNewBranch" .= which +-- : case reason of +-- IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> +-- [ "errorKind" .= ("constructorAlias" :: Text), +-- "typeName" .= typeName, +-- "constructorName1" .= constructorName1, +-- "constructorName2" .= constructorName2 +-- ] +-- IncoherentDeclReason'MissingConstructorName typeName -> +-- [ "errorKind" .= ("missingConstructorName" :: Text), +-- "typeName" .= typeName +-- ] +-- IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> +-- [ "errorKind" .= ("constructorAlias" :: Text), +-- "constructorName1" .= constructorName1, +-- "constructorName2" .= constructorName2 +-- ] +-- IncoherentDeclReason'StrayConstructor _ constructorName -> +-- [ "errorKind" .= ("strayConstructor" :: Text), +-- "constructorName" .= constructorName +-- ] +-- ) +-- in case reason of +-- EitherWay.Alice reason -> f "old" reason +-- EitherWay.Bob reason -> f "new" reason +-- NamespaceDiffs.LibFoundAtUnexpectedPath _ -> +-- object +-- [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) +-- ] +-- NamespaceDiffs.MissingEntityError _ -> +-- object +-- [ "errorKind" .= ("missingEntityError" :: Text) +-- ] +-- ] +-- ShareNamespaceDiffStatus'StillComputing -> +-- object +-- [ "diffKind" .= ("computing" :: Text) +-- ] data ShareNamespaceDiffResponse = ShareNamespaceDiffResponse { project :: ProjectShortHand, @@ -92,15 +92,75 @@ data ShareNamespaceDiffResponse = ShareNamespaceDiffResponse instance ToJSON ShareNamespaceDiffResponse where toJSON (ShareNamespaceDiffResponse {diff, project, oldRef, newRef, oldRefHash, newRefHash}) = - object - [ "diff" .= diff, - "project" .= project, - "oldRef" .= oldRef, - "oldRefHash" .= oldRefHash, - "newRef" .= newRef, - "newRefHash" .= newRefHash - ] + object $ + (maybe [] (\v -> ["diff" .= v]) diffProperty) + ++ [ "diffKind" .= diffKindProperty, + "project" .= toJSON project, + "oldRef" .= oldRef, + "oldRefHash" .= oldRefHash, + "newRef" .= newRef, + "newRefHash" .= newRefHash + ] where + diffKindProperty :: Text + diffKindProperty = + case diff of + ShareNamespaceDiffStatus'Ok _ -> "ok" + ShareNamespaceDiffStatus'Error _ -> "error" + ShareNamespaceDiffStatus'StillComputing -> "computing" + + diffProperty :: Maybe Value + diffProperty = + case diff of + ShareNamespaceDiffStatus'Ok diff -> Just (toJSON diff) + ShareNamespaceDiffStatus'Error err -> + Just $ + object + [ "error" + .= case err of + NamespaceDiffs.ImpossibleError _ -> + object + [ "errorKind" .= ("impossibleError" :: Text) + ] + NamespaceDiffs.IncoherentDecl reason -> + let f :: Text -> IncoherentDeclReason -> Value + f which reason = + object + ( "oldOrNewBranch" .= which + : case reason of + IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> + [ "errorKind" .= ("constructorAlias" :: Text), + "typeName" .= typeName, + "constructorName1" .= constructorName1, + "constructorName2" .= constructorName2 + ] + IncoherentDeclReason'MissingConstructorName typeName -> + [ "errorKind" .= ("missingConstructorName" :: Text), + "typeName" .= typeName + ] + IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> + [ "errorKind" .= ("constructorAlias" :: Text), + "constructorName1" .= constructorName1, + "constructorName2" .= constructorName2 + ] + IncoherentDeclReason'StrayConstructor _ constructorName -> + [ "errorKind" .= ("strayConstructor" :: Text), + "constructorName" .= constructorName + ] + ) + in case reason of + EitherWay.Alice reason -> f "old" reason + EitherWay.Bob reason -> f "new" reason + NamespaceDiffs.LibFoundAtUnexpectedPath _ -> + object + [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) + ] + NamespaceDiffs.MissingEntityError _ -> + object + [ "errorKind" .= ("missingEntityError" :: Text) + ] + ] + ShareNamespaceDiffStatus'StillComputing -> Nothing data ShareTermDiffResponse = ShareTermDiffResponse { project :: ProjectShortHand, diff --git a/transcripts/share-apis/contribution-diffs/contribution-diff.json b/transcripts/share-apis/contribution-diffs/contribution-diff.json index b50d9313..9b9f0f23 100644 --- a/transcripts/share-apis/contribution-diffs/contribution-diff.json +++ b/transcripts/share-apis/contribution-diffs/contribution-diff.json @@ -1,282 +1,615 @@ { "body": { "diff": { - "diff": { - "defns": { - "changes": [ - { + "defns": { + "changes": [ + { + "contents": { "contents": { - "contents": { - "aliasFullName": "ATypeAlias", - "aliasShortName": "ATypeAlias", - "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", - "otherNames": [ - "DataAliasMe" - ], - "rendered": { - "bestTypeName": "ATypeAlias", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" + "aliasFullName": "ATypeAlias", + "aliasShortName": "ATypeAlias", + "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", + "otherNames": [ + "DataAliasMe" + ], + "rendered": { + "bestTypeName": "ATypeAlias", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" }, - { - "annotation": null, - "segment": " " + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "ATypeAlias", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "ATypeAlias", - "tag": "HashQualifier" - }, - "segment": "ATypeAlias" + "segment": "ATypeAlias" + }, + { + "annotation": { + "tag": "DelimiterChar" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " + "segment": " = " + }, + { + "annotation": { + "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", + "tag": "TermReference" }, - { - "annotation": { - "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", - "tag": "TermReference" - }, - "segment": "B" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "ATypeAlias", - "DataAliasMe" - ] - } - }, - "tag": "Aliased" + "segment": "B" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "ATypeAlias", + "DataAliasMe" + ] + } }, - "tag": "Data" + "tag": "Aliased" }, - { + "tag": "Data" + }, + { + "contents": { "contents": { - "contents": { - "aliasFullName": "AbilityAlias", - "aliasShortName": "AbilityAlias", - "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "otherNames": [ + "aliasFullName": "AbilityAlias", + "aliasShortName": "AbilityAlias", + "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", + "otherNames": [ + "AbilityAliasMe" + ], + "rendered": { + "bestTypeName": "AbilityAlias", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityAlias", + "tag": "HashQualifier" + }, + "segment": "AbilityAlias" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", + "tag": "TermReference" + }, + "segment": "abilityAliasMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", + "tag": "TypeReference" + }, + "segment": "AbilityAlias" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityAlias", "AbilityAliasMe" - ], - "rendered": { - "bestTypeName": "AbilityAlias", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" + ] + } + }, + "tag": "Aliased" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityDeleteMe", + "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "rendered": { + "bestTypeName": "AbilityDeleteMe", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" }, - { - "annotation": null, - "segment": " " + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityDeleteMe", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "AbilityAlias", - "tag": "HashQualifier" - }, - "segment": "AbilityAlias" + "segment": "AbilityDeleteMe" + }, + { + "annotation": { + "tag": "ControlKeyword" }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", + "tag": "TermReference" }, - { - "annotation": null, - "segment": "\n" + "segment": "abilityDeleteMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", - "tag": "TermReference" - }, - "segment": "abilityAliasMe" + "segment": "{" + }, + { + "annotation": { + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": "AbilityDeleteMe" + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": null, - "segment": " " + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityDeleteMe" + ] + }, + "shortName": "AbilityDeleteMe" + }, + "tag": "Removed" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityNew", + "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "rendered": { + "bestTypeName": "AbilityNew", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "tag": "TypeReference" - }, - "segment": "AbilityAlias" + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityNew", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" + "segment": "AbilityNew" + }, + { + "annotation": { + "tag": "ControlKeyword" }, - { - "annotation": null, - "segment": " " + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", + "tag": "TermReference" }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityAlias", - "AbilityAliasMe" - ] - } + "segment": "abilityNew" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "tag": "TypeReference" + }, + "segment": "AbilityNew" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityNew" + ] }, - "tag": "Aliased" + "shortName": "AbilityNew" }, - "tag": "Ability" + "tag": "Added" }, - { + "tag": "Ability" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "AbilityDeleteMe", - "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", - "rendered": { - "bestTypeName": "AbilityDeleteMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" + "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "newFullName": "AbilityRenamed", + "newShortName": "AbilityRenamed", + "oldNames": [ + "AbilityRenameMe" + ], + "rendered": { + "bestTypeName": "AbilityRenamed", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityRenamed", + "tag": "HashQualifier" + }, + "segment": "AbilityRenamed" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", + "tag": "TermReference" + }, + "segment": "abilityRenameMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": { - "contents": "AbilityDeleteMe", - "tag": "HashQualifier" - }, - "segment": "AbilityDeleteMe" + "segment": "{" + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" + "segment": "AbilityRenamed" + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": null, - "segment": "\n" + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityRenamed" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ { - "annotation": null, - "segment": " " + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", "tag": "TermReference" }, - "segment": "abilityDeleteMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " + "segment": "abilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "tag": "TermReference" + } }, { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + } + ] }, { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", "tag": "TypeReference" }, - "segment": "AbilityDeleteMe" + "segment": "AbilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "tag": "TypeReference" + } }, { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": null, - "segment": " " + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] }, { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ] } ], "tag": "UserObject" }, - "typeDocs": [], - "typeNames": [ - "AbilityDeleteMe" - ] + "diffKind": "diff" }, - "shortName": "AbilityDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "fullName": "AbilityNew", - "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", - "rendered": { - "bestTypeName": "AbilityNew", + "left": { + "bestTypeName": "AbilityUpdateMe", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -292,10 +625,10 @@ }, { "annotation": { - "contents": "AbilityNew", + "contents": "AbilityUpdateMe", "tag": "HashQualifier" }, - "segment": "AbilityNew" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -313,10 +646,10 @@ }, { "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", "tag": "TermReference" }, - "segment": "abilityNew" + "segment": "abilityUpdateMe" }, { "annotation": { @@ -336,10 +669,10 @@ }, { "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", "tag": "TypeReference" }, - "segment": "AbilityNew" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -353,36 +686,21 @@ }, { "annotation": { - "contents": "##Text", + "contents": "##Nat", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Nat" } ], "tag": "UserObject" }, "typeDocs": [], "typeNames": [ - "AbilityNew" + "AbilityUpdateMe" ] }, - "shortName": "AbilityNew" - }, - "tag": "Added" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", - "newFullName": "AbilityRenamed", - "newShortName": "AbilityRenamed", - "oldNames": [ - "AbilityRenameMe" - ], - "rendered": { - "bestTypeName": "AbilityRenamed", + "right": { + "bestTypeName": "AbilityUpdateMe", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -398,10 +716,10 @@ }, { "annotation": { - "contents": "AbilityRenamed", + "contents": "AbilityUpdateMe", "tag": "HashQualifier" }, - "segment": "AbilityRenamed" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -419,10 +737,10 @@ }, { "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", "tag": "TermReference" }, - "segment": "abilityRenameMe" + "segment": "abilityUpdateMe" }, { "annotation": { @@ -442,10 +760,10 @@ }, { "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", "tag": "TypeReference" }, - "segment": "AbilityRenamed" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -459,357 +777,162 @@ }, { "annotation": { - "contents": "##Nat", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityRenamed" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", - "tag": "TermReference" - }, - "segment": "abilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", - "tag": "TermReference" - } - }, - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "tag": "TypeReference" - }, - "segment": "AbilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "tag": "TypeReference" - } - }, - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "AbilityUpdateMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", - "tag": "TermReference" - }, - "segment": "abilityUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "tag": "TypeReference" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityUpdateMe" - ] - }, - "right": { - "bestTypeName": "AbilityUpdateMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", - "tag": "TermReference" - }, - "segment": "abilityUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "tag": "TypeReference" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "tag": "UserObject" + "segment": "Text" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityUpdateMe" + ] + } + }, + "fullName": "AbilityUpdateMe", + "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "newTag": "Ability", + "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "oldTag": "Ability", + "shortName": "AbilityUpdateMe" + }, + "tag": "Updated" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "DataDeleteMe", + "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", + "rendered": { + "bestTypeName": "DataDeleteMe", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "typeDocs": [], - "typeNames": [ - "AbilityUpdateMe" - ] - } + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataDeleteMe", + "tag": "HashQualifier" + }, + "segment": "DataDeleteMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", + "tag": "TermReference" + }, + "segment": "C" + } + ], + "tag": "UserObject" }, - "fullName": "AbilityUpdateMe", - "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "newTag": "Ability", - "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "oldTag": "Ability", - "shortName": "AbilityUpdateMe" + "typeDocs": [], + "typeNames": [ + "DataDeleteMe" + ] }, - "tag": "Updated" + "shortName": "DataDeleteMe" }, - "tag": "Ability" + "tag": "Removed" }, - { + "tag": "Data" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "DataDeleteMe", - "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", - "rendered": { - "bestTypeName": "DataDeleteMe", + "diff": { + "diff": { + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", + "tag": "TermReference" + }, + "segment": "D" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTypeName": "DataUpdateMe", "defnTypeTag": "Data", "typeDefinition": { "contents": [ @@ -825,10 +948,10 @@ }, { "annotation": { - "contents": "DataDeleteMe", + "contents": "DataUpdateMe", "tag": "HashQualifier" }, - "segment": "DataDeleteMe" + "segment": "DataUpdateMe" }, { "annotation": { @@ -838,216 +961,21 @@ }, { "annotation": { - "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", "tag": "TermReference" }, - "segment": "C" + "segment": "D" } ], "tag": "UserObject" }, "typeDocs": [], "typeNames": [ - "DataDeleteMe" + "DataUpdateMe" ] }, - "shortName": "DataDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" - }, - "segment": "D" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", - "tag": "TermReference" - }, - "segment": "D2" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "DataUpdateMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" - }, - "segment": "D" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataUpdateMe" - ] - }, - "right": { - "bestTypeName": "DataUpdateMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", - "tag": "TermReference" - }, - "segment": "D2" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataUpdateMe" - ] - } - }, - "fullName": "DataUpdateMe", - "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", - "newTag": "Data", - "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", - "oldTag": "Data", - "shortName": "DataUpdateMe" - }, - "tag": "Updated" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "fullName": "NewType", - "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", - "rendered": { - "bestTypeName": "NewType", + "right": { + "bestTypeName": "DataUpdateMe", "defnTypeTag": "Data", "typeDefinition": { "contents": [ @@ -1063,10 +991,10 @@ }, { "annotation": { - "contents": "NewType", + "contents": "DataUpdateMe", "tag": "HashQualifier" }, - "segment": "NewType" + "segment": "DataUpdateMe" }, { "annotation": { @@ -1074,337 +1002,919 @@ }, "segment": " = " }, - { - "annotation": { - "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", - "tag": "TermReference" + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "DataUpdateMe" + ] + } + }, + "fullName": "DataUpdateMe", + "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", + "newTag": "Data", + "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", + "oldTag": "Data", + "shortName": "DataUpdateMe" + }, + "tag": "Updated" + }, + "tag": "Data" + }, + { + "contents": { + "contents": { + "fullName": "NewType", + "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", + "rendered": { + "bestTypeName": "NewType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "NewType", + "tag": "HashQualifier" + }, + "segment": "NewType" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", + "tag": "TermReference" + }, + "segment": "X" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "NewType" + ] + }, + "shortName": "NewType" + }, + "tag": "Added" + }, + "tag": "Data" + }, + { + "contents": { + "contents": { + "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", + "newFullName": "RenamedType", + "newShortName": "RenamedType", + "oldNames": [ + "DataRenameMe" + ], + "rendered": { + "bestTypeName": "RenamedType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "RenamedType", + "tag": "HashQualifier" + }, + "segment": "RenamedType" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", + "tag": "TermReference" + }, + "segment": "E" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "RenamedType" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Data" + }, + { + "contents": { + "contents": { + "fullName": "aDoc", + "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + "rendered": { + "bestTermName": "aDoc", + "defnTermTag": "Doc", + "signature": [ + { + "annotation": { + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", + "tag": "TypeReference" + }, + "segment": "Doc2" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", + "tag": "TypeReference" + }, + "segment": "Doc2" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "{{" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": null, + "segment": "Test" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": null, + "segment": "Doc" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "}}" + } + ], + "tag": "UserObject" + }, + "termDocs": [ + [ + "aDoc", + "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + { + "contents": [ + { + "contents": "Test", + "tag": "Word" }, - "segment": "X" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "NewType" + { + "contents": "Doc", + "tag": "Word" + } + ], + "tag": "Paragraph" + } ] - }, - "shortName": "NewType" + ], + "termNames": [ + "aDoc" + ] }, - "tag": "Added" + "shortName": "aDoc" }, - "tag": "Data" + "tag": "Removed" }, - { + "tag": "Doc" + }, + { + "contents": { "contents": { - "contents": { - "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", - "newFullName": "RenamedType", - "newShortName": "RenamedType", - "oldNames": [ - "DataRenameMe" + "aliasFullName": "aTermAlias", + "aliasShortName": "aTermAlias", + "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", + "otherNames": [ + "termAliasMe" + ], + "rendered": { + "bestTermName": "aTermAlias", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } ], - "rendered": { - "bestTypeName": "RenamedType", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "aTermAlias" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "contents": "RenamedType", - "tag": "HashQualifier" - }, - "segment": "RenamedType" + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", - "tag": "TermReference" - }, - "segment": "E" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "RenamedType" - ] - } - }, - "tag": "RenamedFrom" + "segment": "aTermAlias" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "1" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "aTermAlias", + "termAliasMe" + ] + } }, - "tag": "Data" + "tag": "Aliased" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "aDoc", - "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - "rendered": { - "bestTermName": "aDoc", - "defnTermTag": "Doc", - "signature": [ + "fullName": "aTest", + "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", + "rendered": { + "bestTermName": "aTest", + "defnTermTag": "Test", + "signature": [ + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "tag": "TypeReference" + }, + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "]" + } + ], + "termDefinition": { + "contents": [ { "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" + "contents": "aTest", + "tag": "HashQualifier" }, - "segment": "Doc2" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" - }, - "segment": "aDoc" + "segment": "aTest" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DelimiterChar" }, - { - "annotation": null, - "segment": " " + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "tag": "TypeReference" }, - { - "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" - }, - "segment": "Doc2" + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" }, - { - "annotation": null, - "segment": "\n" + "segment": "]" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "aTest", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" - }, - "segment": "aDoc" + "segment": "aTest" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Sequence", + "tag": "TypeReference" }, - { - "annotation": null, - "segment": " " + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", + "tag": "TermReference" }, - { - "annotation": { - "tag": "DocDelimiter" - }, - "segment": "{{" + "segment": "Ok" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": null, - "segment": " " + "segment": "\"Done\"" + }, + { + "annotation": { + "contents": "##Sequence", + "tag": "TypeReference" }, - { - "annotation": null, - "segment": "Test" + "segment": "]" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "aTest" + ] + }, + "shortName": "aTest" + }, + "tag": "Removed" + }, + "tag": "Test" + }, + { + "contents": { + "contents": { + "fullName": "newTerm", + "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", + "rendered": { + "bestTermName": "newTerm", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "newTerm" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": "Doc" + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": null, - "segment": " " + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "DocDelimiter" - }, - "segment": "}}" - } - ], - "tag": "UserObject" - }, - "termDocs": [ - [ - "aDoc", - "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - { - "contents": [ - { - "contents": "Test", - "tag": "Word" - }, - { - "contents": "Doc", - "tag": "Word" - } - ], - "tag": "Paragraph" - } - ] + "segment": "newTerm" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "100" + } ], - "termNames": [ - "aDoc" - ] + "tag": "UserObject" }, - "shortName": "aDoc" + "termDocs": [], + "termNames": [ + "newTerm" + ] }, - "tag": "Removed" + "shortName": "newTerm" }, - "tag": "Doc" + "tag": "Added" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { - "aliasFullName": "aTermAlias", - "aliasShortName": "aTermAlias", - "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", - "otherNames": [ - "termAliasMe" + "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", + "newFullName": "renamedTerm", + "newShortName": "renamedTerm", + "oldNames": [ + "termRenameMe" + ], + "rendered": { + "bestTermName": "renamedTerm", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } ], - "rendered": { - "bestTermName": "aTermAlias", - "defnTermTag": "Plain", - "signature": [ + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "renamedTerm", + "tag": "HashQualifier" + }, + "segment": "renamedTerm" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Nat", "tag": "TypeReference" }, "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "renamedTerm", + "tag": "HashQualifier" + }, + "segment": "renamedTerm" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "3" } ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" - }, - "segment": "aTermAlias" + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "renamedTerm" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "fullName": "termDeleteMe", + "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", + "rendered": { + "bestTermName": "termDeleteMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": "termDeleteMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "termDeleteMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" }, + "segment": "2" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termDeleteMe" + ] + }, + "shortName": "termDeleteMe" + }, + "tag": "Removed" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" - }, - "segment": "aTermAlias" + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": { - "tag": "BindingEquals" + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": " =" + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + } }, { - "annotation": null, - "segment": " " + "diffTag": "both", + "elements": [ + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": { - "tag": "NumericLiteral" + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": "1" + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + } } ], "tag": "UserObject" }, - "termDocs": [], - "termNames": [ - "aTermAlias", - "termAliasMe" - ] - } - }, - "tag": "Aliased" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "fullName": "aTest", - "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", - "rendered": { - "bestTermName": "aTest", - "defnTermTag": "Test", + "diffKind": "diff" + }, + "left": { + "bestTermName": "termDependsOnUpdateMe", + "defnTermTag": "Plain", "signature": [ { "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "]" + "segment": "Text" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "aTest", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "aTest" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1418,22 +1928,10 @@ }, { "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "]" + "segment": "Text" }, { "annotation": null, @@ -1441,10 +1939,10 @@ }, { "annotation": { - "contents": "aTest", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "aTest" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1454,112 +1952,59 @@ }, { "annotation": null, - "segment": " " + "segment": "\n" }, { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" - }, - "segment": "[" + "annotation": null, + "segment": " " }, { "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", - "tag": "TermReference" + "tag": "UseKeyword" }, - "segment": "Ok" - }, - { - "annotation": null, - "segment": " " + "segment": "use " }, { "annotation": { - "tag": "TextLiteral" + "tag": "UsePrefix" }, - "segment": "\"Done\"" + "segment": "Text" }, { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" - }, - "segment": "]" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "aTest" - ] - }, - "shortName": "aTest" - }, - "tag": "Removed" - }, - "tag": "Test" - }, - { - "contents": { - "contents": { - "fullName": "newTerm", - "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", - "rendered": { - "bestTermName": "newTerm", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "annotation": null, + "segment": " " }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ { "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" + "tag": "UseSuffix" }, - "segment": "newTerm" + "segment": "++" }, { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "annotation": null, + "segment": "\n" }, { "annotation": null, - "segment": " " + "segment": " " }, { "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": "Nat" + "segment": "termUpdateMe" }, { "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" - }, - "segment": "newTerm" + "segment": " " }, { "annotation": { - "tag": "BindingEquals" + "contents": "##Text.++", + "tag": "TermReference" }, - "segment": " =" + "segment": "++" }, { "annotation": null, @@ -1567,53 +2012,39 @@ }, { "annotation": { - "tag": "NumericLiteral" + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": "100" + "segment": "termUpdateMe" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "newTerm" + "termDependsOnUpdateMe" ] }, - "shortName": "newTerm" - }, - "tag": "Added" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", - "newFullName": "renamedTerm", - "newShortName": "renamedTerm", - "oldNames": [ - "termRenameMe" - ], - "rendered": { - "bestTermName": "renamedTerm", + "right": { + "bestTermName": "termDependsOnUpdateMe", "defnTermTag": "Plain", "signature": [ { "annotation": { - "contents": "##Nat", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Nat" + "segment": "Text" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "renamedTerm", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "renamedTerm" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1627,10 +2058,10 @@ }, { "annotation": { - "contents": "##Nat", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Nat" + "segment": "Text" }, { "annotation": null, @@ -1638,10 +2069,10 @@ }, { "annotation": { - "contents": "renamedTerm", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "renamedTerm" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1651,58 +2082,23 @@ }, { "annotation": null, - "segment": " " + "segment": "\n" }, { - "annotation": { - "tag": "NumericLiteral" - }, - "segment": "3" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "renamedTerm" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "fullName": "termDeleteMe", - "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", - "rendered": { - "bestTermName": "termDeleteMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "annotation": null, + "segment": " " }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ { "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" + "tag": "UseKeyword" }, - "segment": "termDeleteMe" + "segment": "use " }, { "annotation": { - "tag": "TypeAscriptionColon" + "tag": "UsePrefix" }, - "segment": " :" + "segment": "Text" }, { "annotation": null, @@ -1710,27 +2106,35 @@ }, { "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "tag": "UseSuffix" }, - "segment": "Nat" + "segment": "++" }, { "annotation": null, "segment": "\n" }, + { + "annotation": null, + "segment": " " + }, { "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" }, - "segment": "termDeleteMe" + "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": " " }, { "annotation": { - "tag": "BindingEquals" + "contents": "##Text.++", + "tag": "TermReference" }, - "segment": " =" + "segment": "++" }, { "annotation": null, @@ -1738,962 +2142,556 @@ }, { "annotation": { - "tag": "NumericLiteral" + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" }, - "segment": "2" + "segment": "termUpdateMe" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "termDeleteMe" + "termDependsOnUpdateMe" ] - }, - "shortName": "termDeleteMe" + } }, - "tag": "Removed" + "fullName": "termDependsOnUpdateMe", + "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", + "newTag": "Plain", + "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", + "oldTag": "Plain", + "shortName": "termDependsOnUpdateMe" }, - "tag": "Plain" + "tag": "Propagated" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { + "diff": { "diff": { "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "segment": " =" }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + { + "annotation": null, + "segment": " " } - }, - { - "diffTag": "both", - "elements": [ - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" - }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + "segment": "\"original\"" } - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termDependsOnUpdateMe", - "defnTermTag": "Plain", - "signature": [ + ] + }, { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"updated\"" + } + ] } ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " - }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termDependsOnUpdateMe" - ] + "tag": "UserObject" }, - "right": { - "bestTermName": "termDependsOnUpdateMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " - }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termDependsOnUpdateMe" - ] - } + "diffKind": "diff" }, - "fullName": "termDependsOnUpdateMe", - "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", - "newTag": "Plain", - "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", - "oldTag": "Plain", - "shortName": "termDependsOnUpdateMe" - }, - "tag": "Propagated" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - } - ] + "left": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"original\"" - } - ] + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"updated\"" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "\"original\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + }, + "right": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"original\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - }, - "right": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"updated\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - } - }, - "fullName": "termUpdateMe", - "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "newTag": "Plain", - "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "oldTag": "Plain", - "shortName": "termUpdateMe" + "segment": "\"updated\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + } }, - "tag": "Updated" + "fullName": "termUpdateMe", + "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "newTag": "Plain", + "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "oldTag": "Plain", + "shortName": "termUpdateMe" }, - "tag": "Plain" - } - ], - "children": [ - { - "contents": { - "changes": [], - "children": [ - { - "contents": { - "changes": [ - { + "tag": "Updated" + }, + "tag": "Plain" + } + ], + "children": [ + { + "contents": { + "changes": [], + "children": [ + { + "contents": { + "changes": [ + { + "contents": { "contents": { - "contents": { - "fullName": "a.definition.at.path1", - "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", - "rendered": { - "bestTermName": "path1", - "defnTermTag": "Plain", - "signature": [ + "fullName": "a.definition.at.path1", + "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", + "rendered": { + "bestTermName": "path1", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path1" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path1" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path1" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "a.definition.at.path1" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"definition at path\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "a.definition.at.path1" - ] + "segment": "\"definition at path\"" + } + ], + "tag": "UserObject" }, - "shortName": "path1" + "termDocs": [], + "termNames": [ + "a.definition.at.path1" + ] }, - "tag": "Removed" + "shortName": "path1" }, - "tag": "Plain" + "tag": "Removed" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "a.definition.at.path2", - "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", - "rendered": { - "bestTermName": "path2", - "defnTermTag": "Plain", - "signature": [ + "fullName": "a.definition.at.path2", + "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", + "rendered": { + "bestTermName": "path2", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path2" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path2" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path2" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "a.definition.at.path2" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"definition at path2\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "a.definition.at.path2" - ] + "segment": "\"definition at path2\"" + } + ], + "tag": "UserObject" }, - "shortName": "path2" + "termDocs": [], + "termNames": [ + "a.definition.at.path2" + ] }, - "tag": "Removed" + "shortName": "path2" }, - "tag": "Plain" - } - ], - "children": [] - }, - "path": "definition.at" + "tag": "Removed" + }, + "tag": "Plain" + } + ], + "children": [] }, - { - "contents": { - "changes": [ - { + "path": "definition.at" + }, + { + "contents": { + "changes": [ + { + "contents": { "contents": { - "contents": { - "fullName": "a.different.path", - "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", - "rendered": { - "bestTermName": "path", - "defnTermTag": "Plain", - "signature": [ + "fullName": "a.different.path", + "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", + "rendered": { + "bestTermName": "path", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" + }, + "segment": "a.different.path" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" - }, - "segment": "a.different.path" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" - }, - "segment": "a.different.path" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "a.different.path" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"definition at different path\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "a.different.path" - ] + "segment": "\"definition at different path\"" + } + ], + "tag": "UserObject" }, - "shortName": "path" + "termDocs": [], + "termNames": [ + "a.different.path" + ] }, - "tag": "Removed" + "shortName": "path" }, - "tag": "Plain" - } - ], - "children": [] - }, - "path": "different" - } - ] - }, - "path": "a" - } - ] - }, - "libdeps": [] + "tag": "Removed" + }, + "tag": "Plain" + } + ], + "children": [] + }, + "path": "different" + } + ] + }, + "path": "a" + } + ] }, - "diffKind": "ok" + "libdeps": [] }, + "diffKind": "ok", "newRef": "diff-end", "newRefHash": "#f2bjgi4tm53bf6dcfcukt5a6as3ktlrbiacnqq81nco8i4g7dg6pt14vmc1b7ulsb7rt683qjt2rvg9u92uo5mk1gaqgo8cl30umep8", "oldRef": "diff-start", diff --git a/transcripts/share-apis/contribution-diffs/namespace-diff.json b/transcripts/share-apis/contribution-diffs/namespace-diff.json index b50d9313..9b9f0f23 100644 --- a/transcripts/share-apis/contribution-diffs/namespace-diff.json +++ b/transcripts/share-apis/contribution-diffs/namespace-diff.json @@ -1,282 +1,615 @@ { "body": { "diff": { - "diff": { - "defns": { - "changes": [ - { + "defns": { + "changes": [ + { + "contents": { "contents": { - "contents": { - "aliasFullName": "ATypeAlias", - "aliasShortName": "ATypeAlias", - "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", - "otherNames": [ - "DataAliasMe" - ], - "rendered": { - "bestTypeName": "ATypeAlias", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" + "aliasFullName": "ATypeAlias", + "aliasShortName": "ATypeAlias", + "hash": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88", + "otherNames": [ + "DataAliasMe" + ], + "rendered": { + "bestTypeName": "ATypeAlias", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" }, - { - "annotation": null, - "segment": " " + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "ATypeAlias", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "ATypeAlias", - "tag": "HashQualifier" - }, - "segment": "ATypeAlias" + "segment": "ATypeAlias" + }, + { + "annotation": { + "tag": "DelimiterChar" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " + "segment": " = " + }, + { + "annotation": { + "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", + "tag": "TermReference" }, - { - "annotation": { - "contents": "#keu02n8is0irijd65cvuos41kukj3f4ni18mmnudrbll2epo6ftd03nt9l0vqc4fvg98198tefgoupco4o0d0gvnigqgr1bmo2neo88#d0", - "tag": "TermReference" - }, - "segment": "B" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "ATypeAlias", - "DataAliasMe" - ] - } - }, - "tag": "Aliased" + "segment": "B" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "ATypeAlias", + "DataAliasMe" + ] + } }, - "tag": "Data" + "tag": "Aliased" }, - { + "tag": "Data" + }, + { + "contents": { "contents": { - "contents": { - "aliasFullName": "AbilityAlias", - "aliasShortName": "AbilityAlias", - "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "otherNames": [ + "aliasFullName": "AbilityAlias", + "aliasShortName": "AbilityAlias", + "hash": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", + "otherNames": [ + "AbilityAliasMe" + ], + "rendered": { + "bestTypeName": "AbilityAlias", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityAlias", + "tag": "HashQualifier" + }, + "segment": "AbilityAlias" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", + "tag": "TermReference" + }, + "segment": "abilityAliasMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", + "tag": "TypeReference" + }, + "segment": "AbilityAlias" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityAlias", "AbilityAliasMe" - ], - "rendered": { - "bestTypeName": "AbilityAlias", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" + ] + } + }, + "tag": "Aliased" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityDeleteMe", + "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "rendered": { + "bestTypeName": "AbilityDeleteMe", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" }, - { - "annotation": null, - "segment": " " + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityDeleteMe", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "AbilityAlias", - "tag": "HashQualifier" - }, - "segment": "AbilityAlias" + "segment": "AbilityDeleteMe" + }, + { + "annotation": { + "tag": "ControlKeyword" }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", + "tag": "TermReference" }, - { - "annotation": null, - "segment": "\n" + "segment": "abilityDeleteMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o#a0", - "tag": "TermReference" - }, - "segment": "abilityAliasMe" + "segment": "{" + }, + { + "annotation": { + "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": "AbilityDeleteMe" + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": null, - "segment": " " + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityDeleteMe" + ] + }, + "shortName": "AbilityDeleteMe" + }, + "tag": "Removed" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "AbilityNew", + "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "rendered": { + "bestTypeName": "AbilityNew", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" }, - { - "annotation": { - "contents": "#u9m3jehjj8mtrhh4i4fuk545k3pdged9r0egph91irldf4lc0rsmtma9eoakvv9hoeesciebuqd7kfm0vdnk48gi7q3s7edn5omb65o", - "tag": "TypeReference" - }, - "segment": "AbilityAlias" + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityNew", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" + "segment": "AbilityNew" + }, + { + "annotation": { + "tag": "ControlKeyword" }, - { - "annotation": null, - "segment": " " + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", + "tag": "TermReference" }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityAlias", - "AbilityAliasMe" - ] - } + "segment": "abilityNew" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + }, + { + "annotation": { + "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "tag": "TypeReference" + }, + "segment": "AbilityNew" + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityNew" + ] }, - "tag": "Aliased" + "shortName": "AbilityNew" }, - "tag": "Ability" + "tag": "Added" }, - { + "tag": "Ability" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "AbilityDeleteMe", - "hash": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", - "rendered": { - "bestTypeName": "AbilityDeleteMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" + "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "newFullName": "AbilityRenamed", + "newShortName": "AbilityRenamed", + "oldNames": [ + "AbilityRenameMe" + ], + "rendered": { + "bestTypeName": "AbilityRenamed", + "defnTypeTag": "Ability", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityRenamed", + "tag": "HashQualifier" + }, + "segment": "AbilityRenamed" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", + "tag": "TermReference" + }, + "segment": "abilityRenameMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": { - "contents": "AbilityDeleteMe", - "tag": "HashQualifier" - }, - "segment": "AbilityDeleteMe" + "segment": "{" + }, + { + "annotation": { + "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" + "segment": "AbilityRenamed" + }, + { + "annotation": { + "tag": "AbilityBraces" }, - { - "annotation": null, - "segment": "\n" + "segment": "}" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityRenamed" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ { - "annotation": null, - "segment": " " + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "ability" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "AbilityUpdateMe", + "tag": "HashQualifier" + }, + "segment": "AbilityUpdateMe" + }, + { + "annotation": { + "tag": "ControlKeyword" + }, + "segment": " where" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg#a0", + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", "tag": "TermReference" }, - "segment": "abilityDeleteMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " + "segment": "abilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", + "tag": "TermReference" + } }, { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "{" + } + ] }, { - "annotation": { - "contents": "#i201btc2422jlmnric78btv3kl1palljsgc55mvm6rb9ofdos9u8mh2jd70uev381oiun4todb8vhkvvpteieshbfsot4slo9cgrjcg", + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", "tag": "TypeReference" }, - "segment": "AbilityDeleteMe" + "segment": "AbilityUpdateMe", + "toAnnotation": { + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "tag": "TypeReference" + } }, { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "AbilityBraces" + }, + "segment": "}" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": null, - "segment": " " + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] }, { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ] } ], "tag": "UserObject" }, - "typeDocs": [], - "typeNames": [ - "AbilityDeleteMe" - ] + "diffKind": "diff" }, - "shortName": "AbilityDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "fullName": "AbilityNew", - "hash": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", - "rendered": { - "bestTypeName": "AbilityNew", + "left": { + "bestTypeName": "AbilityUpdateMe", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -292,10 +625,10 @@ }, { "annotation": { - "contents": "AbilityNew", + "contents": "AbilityUpdateMe", "tag": "HashQualifier" }, - "segment": "AbilityNew" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -313,10 +646,10 @@ }, { "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0#a0", + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", "tag": "TermReference" }, - "segment": "abilityNew" + "segment": "abilityUpdateMe" }, { "annotation": { @@ -336,10 +669,10 @@ }, { "annotation": { - "contents": "#n7jj1pvi6a8689nggmnlhmn8hvkjiu4j5563kojf57dcf8dribv5suliht31nbpgc4501h26geepfg5o8jiid45h6ccmf8ogqu39am0", + "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", "tag": "TypeReference" }, - "segment": "AbilityNew" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -353,36 +686,21 @@ }, { "annotation": { - "contents": "##Text", + "contents": "##Nat", "tag": "TypeReference" }, - "segment": "Text" + "segment": "Nat" } ], "tag": "UserObject" }, "typeDocs": [], "typeNames": [ - "AbilityNew" + "AbilityUpdateMe" ] }, - "shortName": "AbilityNew" - }, - "tag": "Added" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "hash": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", - "newFullName": "AbilityRenamed", - "newShortName": "AbilityRenamed", - "oldNames": [ - "AbilityRenameMe" - ], - "rendered": { - "bestTypeName": "AbilityRenamed", + "right": { + "bestTypeName": "AbilityUpdateMe", "defnTypeTag": "Ability", "typeDefinition": { "contents": [ @@ -398,10 +716,10 @@ }, { "annotation": { - "contents": "AbilityRenamed", + "contents": "AbilityUpdateMe", "tag": "HashQualifier" }, - "segment": "AbilityRenamed" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -419,10 +737,10 @@ }, { "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do#a0", + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", "tag": "TermReference" }, - "segment": "abilityRenameMe" + "segment": "abilityUpdateMe" }, { "annotation": { @@ -442,10 +760,10 @@ }, { "annotation": { - "contents": "#lh3ufh51cghv5sn14ckq9f2urei00i6adqj3d0vovc51c6f18bhauqfjhkm34227ediga6mc5dp58inn4j714rhenig2jsps9ima7do", + "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", "tag": "TypeReference" }, - "segment": "AbilityRenamed" + "segment": "AbilityUpdateMe" }, { "annotation": { @@ -459,357 +777,162 @@ }, { "annotation": { - "contents": "##Nat", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityRenamed" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Ability" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", - "tag": "TermReference" - }, - "segment": "abilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", - "tag": "TermReference" - } - }, - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "tag": "TypeReference" - }, - "segment": "AbilityUpdateMe", - "toAnnotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "tag": "TypeReference" - } - }, - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "AbilityUpdateMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0#a0", - "tag": "TermReference" - }, - "segment": "abilityUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "tag": "TypeReference" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "AbilityUpdateMe" - ] - }, - "right": { - "bestTypeName": "AbilityUpdateMe", - "defnTypeTag": "Ability", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "ability" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "AbilityUpdateMe", - "tag": "HashQualifier" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "ControlKeyword" - }, - "segment": " where" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng#a0", - "tag": "TermReference" - }, - "segment": "abilityUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "{" - }, - { - "annotation": { - "contents": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "tag": "TypeReference" - }, - "segment": "AbilityUpdateMe" - }, - { - "annotation": { - "tag": "AbilityBraces" - }, - "segment": "}" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "tag": "UserObject" + "segment": "Text" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "AbilityUpdateMe" + ] + } + }, + "fullName": "AbilityUpdateMe", + "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", + "newTag": "Ability", + "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", + "oldTag": "Ability", + "shortName": "AbilityUpdateMe" + }, + "tag": "Updated" + }, + "tag": "Ability" + }, + { + "contents": { + "contents": { + "fullName": "DataDeleteMe", + "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", + "rendered": { + "bestTypeName": "DataDeleteMe", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" }, - "typeDocs": [], - "typeNames": [ - "AbilityUpdateMe" - ] - } + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataDeleteMe", + "tag": "HashQualifier" + }, + "segment": "DataDeleteMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", + "tag": "TermReference" + }, + "segment": "C" + } + ], + "tag": "UserObject" }, - "fullName": "AbilityUpdateMe", - "newHash": "#nnulmopbjndcs4si1mop30dm01nlum2k7m6j4mmd1df2e63m09lchh2j1gkqd4gua3bl0g3j6hgn76rmc495au8cpr0t83oqoho0sng", - "newTag": "Ability", - "oldHash": "#8u70g0vaddp9jm3egoq434qialp8hdnjfh8ah8mqjau0i5lmdikt9qbe491ss53i71976fftb2o90ii6gckvs0i2lhovs1n6h0huhb0", - "oldTag": "Ability", - "shortName": "AbilityUpdateMe" + "typeDocs": [], + "typeNames": [ + "DataDeleteMe" + ] }, - "tag": "Updated" + "shortName": "DataDeleteMe" }, - "tag": "Ability" + "tag": "Removed" }, - { + "tag": "Data" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "DataDeleteMe", - "hash": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o", - "rendered": { - "bestTypeName": "DataDeleteMe", + "diff": { + "diff": { + "diff": { + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "DataUpdateMe", + "tag": "HashQualifier" + }, + "segment": "DataUpdateMe" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", + "tag": "TermReference" + }, + "segment": "D" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTypeName": "DataUpdateMe", "defnTypeTag": "Data", "typeDefinition": { "contents": [ @@ -825,10 +948,10 @@ }, { "annotation": { - "contents": "DataDeleteMe", + "contents": "DataUpdateMe", "tag": "HashQualifier" }, - "segment": "DataDeleteMe" + "segment": "DataUpdateMe" }, { "annotation": { @@ -838,216 +961,21 @@ }, { "annotation": { - "contents": "#fhc8jn2bhvfdnfr89dv2jf7tekuesna7gvje4ck6lfheh9rb184q4ddd29vm9mvfm6u1a98kpgditn8vb09durtel67rpof1c62535o#d0", + "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", "tag": "TermReference" }, - "segment": "C" + "segment": "D" } ], "tag": "UserObject" }, "typeDocs": [], "typeNames": [ - "DataDeleteMe" + "DataUpdateMe" ] }, - "shortName": "DataDeleteMe" - }, - "tag": "Removed" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - } - ] - }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" - }, - "segment": "D" - } - ] - }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", - "tag": "TermReference" - }, - "segment": "D2" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTypeName": "DataUpdateMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o#d0", - "tag": "TermReference" - }, - "segment": "D" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataUpdateMe" - ] - }, - "right": { - "bestTypeName": "DataUpdateMe", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "DataUpdateMe", - "tag": "HashQualifier" - }, - "segment": "DataUpdateMe" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " - }, - { - "annotation": { - "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", - "tag": "TermReference" - }, - "segment": "D2" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "DataUpdateMe" - ] - } - }, - "fullName": "DataUpdateMe", - "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", - "newTag": "Data", - "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", - "oldTag": "Data", - "shortName": "DataUpdateMe" - }, - "tag": "Updated" - }, - "tag": "Data" - }, - { - "contents": { - "contents": { - "fullName": "NewType", - "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", - "rendered": { - "bestTypeName": "NewType", + "right": { + "bestTypeName": "DataUpdateMe", "defnTypeTag": "Data", "typeDefinition": { "contents": [ @@ -1063,10 +991,10 @@ }, { "annotation": { - "contents": "NewType", + "contents": "DataUpdateMe", "tag": "HashQualifier" }, - "segment": "NewType" + "segment": "DataUpdateMe" }, { "annotation": { @@ -1074,337 +1002,919 @@ }, "segment": " = " }, - { - "annotation": { - "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", - "tag": "TermReference" + { + "annotation": { + "contents": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go#d0", + "tag": "TermReference" + }, + "segment": "D2" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "DataUpdateMe" + ] + } + }, + "fullName": "DataUpdateMe", + "newHash": "#6t7t8lem3bmu3j7bsid4omn8gej2gl57ffmkp0ef6qndhndh2q3q6dd1j9akl653r3vtifsunovvbmbjh0iqc7n6rhp4imnsghhe6go", + "newTag": "Data", + "oldHash": "#a2bvb3g2l1mkijg24ogg0t23h51pnfepnngk6e3bqfijf4l9ms292t006e8faquo66ctn1ho35vtps13m6evbl6bos2guer5j6jcs1o", + "oldTag": "Data", + "shortName": "DataUpdateMe" + }, + "tag": "Updated" + }, + "tag": "Data" + }, + { + "contents": { + "contents": { + "fullName": "NewType", + "hash": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg", + "rendered": { + "bestTypeName": "NewType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "NewType", + "tag": "HashQualifier" + }, + "segment": "NewType" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#rmntisgmjlrtq6kja30at01q04aeq2p17q806li6v509bn117tq9tc3gd3m33lhdgimen1tjdn4tqiu2r11k7ie9oibng1n1i275cdg#d0", + "tag": "TermReference" + }, + "segment": "X" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "NewType" + ] + }, + "shortName": "NewType" + }, + "tag": "Added" + }, + "tag": "Data" + }, + { + "contents": { + "contents": { + "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", + "newFullName": "RenamedType", + "newShortName": "RenamedType", + "oldNames": [ + "DataRenameMe" + ], + "rendered": { + "bestTypeName": "RenamedType", + "defnTypeTag": "Data", + "typeDefinition": { + "contents": [ + { + "annotation": { + "tag": "DataTypeKeyword" + }, + "segment": "type" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "RenamedType", + "tag": "HashQualifier" + }, + "segment": "RenamedType" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": " = " + }, + { + "annotation": { + "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", + "tag": "TermReference" + }, + "segment": "E" + } + ], + "tag": "UserObject" + }, + "typeDocs": [], + "typeNames": [ + "RenamedType" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Data" + }, + { + "contents": { + "contents": { + "fullName": "aDoc", + "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + "rendered": { + "bestTermName": "aDoc", + "defnTermTag": "Doc", + "signature": [ + { + "annotation": { + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", + "tag": "TypeReference" + }, + "segment": "Doc2" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", + "tag": "TypeReference" + }, + "segment": "Doc2" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "aDoc", + "tag": "HashQualifier" + }, + "segment": "aDoc" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "{{" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": null, + "segment": "Test" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": null, + "segment": "Doc" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DocDelimiter" + }, + "segment": "}}" + } + ], + "tag": "UserObject" + }, + "termDocs": [ + [ + "aDoc", + "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", + { + "contents": [ + { + "contents": "Test", + "tag": "Word" }, - "segment": "X" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "NewType" + { + "contents": "Doc", + "tag": "Word" + } + ], + "tag": "Paragraph" + } ] - }, - "shortName": "NewType" + ], + "termNames": [ + "aDoc" + ] }, - "tag": "Added" + "shortName": "aDoc" }, - "tag": "Data" + "tag": "Removed" }, - { + "tag": "Doc" + }, + { + "contents": { "contents": { - "contents": { - "hash": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg", - "newFullName": "RenamedType", - "newShortName": "RenamedType", - "oldNames": [ - "DataRenameMe" + "aliasFullName": "aTermAlias", + "aliasShortName": "aTermAlias", + "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", + "otherNames": [ + "termAliasMe" + ], + "rendered": { + "bestTermName": "aTermAlias", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } ], - "rendered": { - "bestTypeName": "RenamedType", - "defnTypeTag": "Data", - "typeDefinition": { - "contents": [ - { - "annotation": { - "tag": "DataTypeKeyword" - }, - "segment": "type" + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "aTermAlias" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "contents": "RenamedType", - "tag": "HashQualifier" - }, - "segment": "RenamedType" + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": " = " + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "aTermAlias", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "#hb2ubbk0c6347s5eqic78f26truhgro1ueh7r8invme3hnalmnv880tgpafpeo5kaaihonoph8o7pmhad8mr2e25m0hhor9lr34skhg#d0", - "tag": "TermReference" - }, - "segment": "E" - } - ], - "tag": "UserObject" - }, - "typeDocs": [], - "typeNames": [ - "RenamedType" - ] - } - }, - "tag": "RenamedFrom" + "segment": "aTermAlias" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "1" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "aTermAlias", + "termAliasMe" + ] + } }, - "tag": "Data" + "tag": "Aliased" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "aDoc", - "hash": "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - "rendered": { - "bestTermName": "aDoc", - "defnTermTag": "Doc", - "signature": [ + "fullName": "aTest", + "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", + "rendered": { + "bestTermName": "aTest", + "defnTermTag": "Test", + "signature": [ + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "tag": "TypeReference" + }, + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" + }, + "segment": "]" + } + ], + "termDefinition": { + "contents": [ { "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" + "contents": "aTest", + "tag": "HashQualifier" }, - "segment": "Doc2" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" - }, - "segment": "aDoc" + "segment": "aTest" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "DelimiterChar" }, - { - "annotation": null, - "segment": " " + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "tag": "TypeReference" }, - { - "annotation": { - "contents": "#ej86si0ur1lsjade71dojr25phk9bbom9rdks6dltolos5tjivakujcriqe02npba53n9gd7tkh8bmv08ttjb9t35lq2ch5heshqcs0", - "tag": "TypeReference" - }, - "segment": "Doc2" + "segment": "Result" + }, + { + "annotation": { + "tag": "DelimiterChar" }, - { - "annotation": null, - "segment": "\n" + "segment": "]" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "aTest", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "aDoc", - "tag": "HashQualifier" - }, - "segment": "aDoc" + "segment": "aTest" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Sequence", + "tag": "TypeReference" }, - { - "annotation": null, - "segment": " " + "segment": "[" + }, + { + "annotation": { + "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", + "tag": "TermReference" }, - { - "annotation": { - "tag": "DocDelimiter" - }, - "segment": "{{" + "segment": "Ok" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": null, - "segment": " " + "segment": "\"Done\"" + }, + { + "annotation": { + "contents": "##Sequence", + "tag": "TypeReference" }, - { - "annotation": null, - "segment": "Test" + "segment": "]" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "aTest" + ] + }, + "shortName": "aTest" + }, + "tag": "Removed" + }, + "tag": "Test" + }, + { + "contents": { + "contents": { + "fullName": "newTerm", + "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", + "rendered": { + "bestTermName": "newTerm", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "newTerm" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": "Doc" + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": null, - "segment": " " + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "newTerm", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "DocDelimiter" - }, - "segment": "}}" - } - ], - "tag": "UserObject" - }, - "termDocs": [ - [ - "aDoc", - "#areni4s9liksvfs3923a4ub81qpu37f964fqhbq832artpff8vm1em45ic0k2hlkv4nn08u712ibvjo9b4fl5u19o65g9medo7645i8", - { - "contents": [ - { - "contents": "Test", - "tag": "Word" - }, - { - "contents": "Doc", - "tag": "Word" - } - ], - "tag": "Paragraph" - } - ] + "segment": "newTerm" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "100" + } ], - "termNames": [ - "aDoc" - ] + "tag": "UserObject" }, - "shortName": "aDoc" + "termDocs": [], + "termNames": [ + "newTerm" + ] }, - "tag": "Removed" + "shortName": "newTerm" }, - "tag": "Doc" + "tag": "Added" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { - "aliasFullName": "aTermAlias", - "aliasShortName": "aTermAlias", - "hash": "#gjmq673r1vrurfotlnirv7vutdhm6sa3s02em5g22kk606mv6duvv8be402dv79312i4a0onepq5bo7citsodvq2g720nttj0ee9p0g", - "otherNames": [ - "termAliasMe" + "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", + "newFullName": "renamedTerm", + "newShortName": "renamedTerm", + "oldNames": [ + "termRenameMe" + ], + "rendered": { + "bestTermName": "renamedTerm", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } ], - "rendered": { - "bestTermName": "aTermAlias", - "defnTermTag": "Plain", - "signature": [ + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "renamedTerm", + "tag": "HashQualifier" + }, + "segment": "renamedTerm" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Nat", "tag": "TypeReference" }, "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "renamedTerm", + "tag": "HashQualifier" + }, + "segment": "renamedTerm" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" + }, + "segment": "3" } ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" - }, - "segment": "aTermAlias" + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "renamedTerm" + ] + } + }, + "tag": "RenamedFrom" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "fullName": "termDeleteMe", + "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", + "rendered": { + "bestTermName": "termDeleteMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" + }, + "segment": "Nat" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": "termDeleteMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Nat", + "tag": "TypeReference" }, - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" - }, - "segment": "Nat" + "segment": "Nat" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDeleteMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "termDeleteMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "NumericLiteral" }, + "segment": "2" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termDeleteMe" + ] + }, + "shortName": "termDeleteMe" + }, + "tag": "Removed" + }, + "tag": "Plain" + }, + { + "contents": { + "contents": { + "diff": { + "diff": { + "diff": { + "contents": [ { - "annotation": { - "contents": "aTermAlias", - "tag": "HashQualifier" - }, - "segment": "aTermAlias" + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termDependsOnUpdateMe", + "tag": "HashQualifier" + }, + "segment": "termDependsOnUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" + }, + "segment": " =" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseKeyword" + }, + "segment": "use " + }, + { + "annotation": { + "tag": "UsePrefix" + }, + "segment": "Text" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "UseSuffix" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": { - "tag": "BindingEquals" + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": " =" + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + } }, { - "annotation": null, - "segment": " " + "diffTag": "both", + "elements": [ + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text.++", + "tag": "TermReference" + }, + "segment": "++" + }, + { + "annotation": null, + "segment": " " + } + ] }, { - "annotation": { - "tag": "NumericLiteral" + "diffTag": "annotationChange", + "fromAnnotation": { + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": "1" + "segment": "termUpdateMe", + "toAnnotation": { + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" + } } ], "tag": "UserObject" }, - "termDocs": [], - "termNames": [ - "aTermAlias", - "termAliasMe" - ] - } - }, - "tag": "Aliased" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "fullName": "aTest", - "hash": "#qak36j7cshv12m9meuc97ovllqm8k2i305sh4oq5dbo4834t7atugsdpto6mou1tch2b3q9j2hbi23gdf4jpth7m97mannv9noucgl8", - "rendered": { - "bestTermName": "aTest", - "defnTermTag": "Test", + "diffKind": "diff" + }, + "left": { + "bestTermName": "termDependsOnUpdateMe", + "defnTermTag": "Plain", "signature": [ { "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "]" + "segment": "Text" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "aTest", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "aTest" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1418,22 +1928,10 @@ }, { "annotation": { - "tag": "DelimiterChar" - }, - "segment": "[" - }, - { - "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Result" - }, - { - "annotation": { - "tag": "DelimiterChar" - }, - "segment": "]" + "segment": "Text" }, { "annotation": null, @@ -1441,10 +1939,10 @@ }, { "annotation": { - "contents": "aTest", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "aTest" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1454,112 +1952,59 @@ }, { "annotation": null, - "segment": " " + "segment": "\n" }, { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" - }, - "segment": "[" + "annotation": null, + "segment": " " }, { "annotation": { - "contents": "#aql7qk3iud6vs4cvu43aimopoosgk0fnipibdkc3so13adencmibgfn0u5c01r0adei55nkl3ttsjhl8gbj7tr4gnpj63g64ftbq6s0#d1", - "tag": "TermReference" + "tag": "UseKeyword" }, - "segment": "Ok" - }, - { - "annotation": null, - "segment": " " + "segment": "use " }, { "annotation": { - "tag": "TextLiteral" + "tag": "UsePrefix" }, - "segment": "\"Done\"" + "segment": "Text" }, { - "annotation": { - "contents": "##Sequence", - "tag": "TypeReference" - }, - "segment": "]" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "aTest" - ] - }, - "shortName": "aTest" - }, - "tag": "Removed" - }, - "tag": "Test" - }, - { - "contents": { - "contents": { - "fullName": "newTerm", - "hash": "#u1qsl3nk5t2svl58ifqepem851775qca9p4hc10j3iordu1v7u8e16oodui9kvt2c0j1cbc50avado53bl2vt3pphrfj9mhbut1ipm8", - "rendered": { - "bestTermName": "newTerm", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "annotation": null, + "segment": " " }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ { "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" + "tag": "UseSuffix" }, - "segment": "newTerm" + "segment": "++" }, { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "annotation": null, + "segment": "\n" }, { "annotation": null, - "segment": " " + "segment": " " }, { "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": "Nat" + "segment": "termUpdateMe" }, { "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "newTerm", - "tag": "HashQualifier" - }, - "segment": "newTerm" + "segment": " " }, { "annotation": { - "tag": "BindingEquals" + "contents": "##Text.++", + "tag": "TermReference" }, - "segment": " =" + "segment": "++" }, { "annotation": null, @@ -1567,53 +2012,39 @@ }, { "annotation": { - "tag": "NumericLiteral" + "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "tag": "TermReference" }, - "segment": "100" + "segment": "termUpdateMe" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "newTerm" + "termDependsOnUpdateMe" ] }, - "shortName": "newTerm" - }, - "tag": "Added" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "hash": "#f3lgjvjqoocpt8v6kdgd2bgthh11a7md3qdp9rf5datccmo580btjd5bt5dro3irqs0is7vm7s1dphddjbtufch620te7ef7canmjj8", - "newFullName": "renamedTerm", - "newShortName": "renamedTerm", - "oldNames": [ - "termRenameMe" - ], - "rendered": { - "bestTermName": "renamedTerm", + "right": { + "bestTermName": "termDependsOnUpdateMe", "defnTermTag": "Plain", "signature": [ { "annotation": { - "contents": "##Nat", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Nat" + "segment": "Text" } ], "termDefinition": { "contents": [ { "annotation": { - "contents": "renamedTerm", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "renamedTerm" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1627,10 +2058,10 @@ }, { "annotation": { - "contents": "##Nat", + "contents": "##Text", "tag": "TypeReference" }, - "segment": "Nat" + "segment": "Text" }, { "annotation": null, @@ -1638,10 +2069,10 @@ }, { "annotation": { - "contents": "renamedTerm", + "contents": "termDependsOnUpdateMe", "tag": "HashQualifier" }, - "segment": "renamedTerm" + "segment": "termDependsOnUpdateMe" }, { "annotation": { @@ -1651,58 +2082,23 @@ }, { "annotation": null, - "segment": " " + "segment": "\n" }, { - "annotation": { - "tag": "NumericLiteral" - }, - "segment": "3" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "renamedTerm" - ] - } - }, - "tag": "RenamedFrom" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "fullName": "termDeleteMe", - "hash": "#dcgdua2lj6upd1ah5v0qp09gjsej0d77d87fu6qn8e2qrssnlnmuinoio46hiu53magr7qn8vnqke8ndt0v76700o5u8gcvo7st28jg", - "rendered": { - "bestTermName": "termDeleteMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "annotation": null, + "segment": " " }, - "segment": "Nat" - } - ], - "termDefinition": { - "contents": [ { "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" + "tag": "UseKeyword" }, - "segment": "termDeleteMe" + "segment": "use " }, { "annotation": { - "tag": "TypeAscriptionColon" + "tag": "UsePrefix" }, - "segment": " :" + "segment": "Text" }, { "annotation": null, @@ -1710,27 +2106,35 @@ }, { "annotation": { - "contents": "##Nat", - "tag": "TypeReference" + "tag": "UseSuffix" }, - "segment": "Nat" + "segment": "++" }, { "annotation": null, "segment": "\n" }, + { + "annotation": null, + "segment": " " + }, { "annotation": { - "contents": "termDeleteMe", - "tag": "HashQualifier" + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" }, - "segment": "termDeleteMe" + "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": " " }, { "annotation": { - "tag": "BindingEquals" + "contents": "##Text.++", + "tag": "TermReference" }, - "segment": " =" + "segment": "++" }, { "annotation": null, @@ -1738,962 +2142,556 @@ }, { "annotation": { - "tag": "NumericLiteral" + "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "tag": "TermReference" }, - "segment": "2" + "segment": "termUpdateMe" } ], "tag": "UserObject" }, "termDocs": [], "termNames": [ - "termDeleteMe" + "termDependsOnUpdateMe" ] - }, - "shortName": "termDeleteMe" + } }, - "tag": "Removed" + "fullName": "termDependsOnUpdateMe", + "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", + "newTag": "Plain", + "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", + "oldTag": "Plain", + "shortName": "termDependsOnUpdateMe" }, - "tag": "Plain" + "tag": "Propagated" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { + "diff": { "diff": { "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" + "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" + "segment": " =" }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + { + "annotation": null, + "segment": " " } - }, - { - "diffTag": "both", - "elements": [ - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": null, - "segment": " " - } - ] - }, - { - "diffTag": "annotationChange", - "fromAnnotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" - }, - "segment": "termUpdateMe", - "toAnnotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" + "segment": "\"original\"" } - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termDependsOnUpdateMe", - "defnTermTag": "Plain", - "signature": [ + ] + }, { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" + }, + "segment": "\"updated\"" + } + ] } ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " - }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termDependsOnUpdateMe" - ] + "tag": "UserObject" }, - "right": { - "bestTermName": "termDependsOnUpdateMe", - "defnTermTag": "Plain", - "signature": [ - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termDependsOnUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termDependsOnUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseKeyword" - }, - "segment": "use " - }, - { - "annotation": { - "tag": "UsePrefix" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "tag": "UseSuffix" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text.++", - "tag": "TermReference" - }, - "segment": "++" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "tag": "TermReference" - }, - "segment": "termUpdateMe" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termDependsOnUpdateMe" - ] - } + "diffKind": "diff" }, - "fullName": "termDependsOnUpdateMe", - "newHash": "#t3u2jnk3eej5hrcrfr80vqiaj7n26grg15n4eb67bd1601jb65ikhbfdk18eeirovmaithk3ipukum6qnhttld43ovitj01kdkd4jrg", - "newTag": "Plain", - "oldHash": "#8imj19nvqqdtl1jd9ns5fksnuh4slku9hoi3sl7dh353k7o209eek4aievkp1sbqq5lqpgqouvf00k5b6t1fkv8omnpsnvmpu0a5lr8", - "oldTag": "Plain", - "shortName": "termDependsOnUpdateMe" - }, - "tag": "Propagated" - }, - "tag": "Plain" - }, - { - "contents": { - "contents": { - "diff": { - "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" - }, - { - "annotation": null, - "segment": " " - } - ] + "left": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"original\"" - } - ] + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"updated\"" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "\"original\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + }, + "right": { + "bestTermName": "termUpdateMe", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"original\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - }, - "right": { - "bestTermName": "termUpdateMe", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "termUpdateMe", - "tag": "HashQualifier" - }, - "segment": "termUpdateMe" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "termUpdateMe", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "termUpdateMe" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"updated\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "termUpdateMe" - ] - } - }, - "fullName": "termUpdateMe", - "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", - "newTag": "Plain", - "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", - "oldTag": "Plain", - "shortName": "termUpdateMe" + "segment": "\"updated\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "termUpdateMe" + ] + } }, - "tag": "Updated" + "fullName": "termUpdateMe", + "newHash": "#711u1t9cjso4t3rhlq2rp491n2n5n4t9o7701053kpj5ouu3kfs2e2l63i879pnsb6ob9fp0gpj18u6fpcl1qosd704h4doklfo734g", + "newTag": "Plain", + "oldHash": "#ofktbubbloi1omgpr09e0t90pg0cnf0lsuuopqese9biqvpdafsuhq0b4dfasbk6g3hp5r7crp4t486fc8bava7q7rrreg9j2volam8", + "oldTag": "Plain", + "shortName": "termUpdateMe" }, - "tag": "Plain" - } - ], - "children": [ - { - "contents": { - "changes": [], - "children": [ - { - "contents": { - "changes": [ - { + "tag": "Updated" + }, + "tag": "Plain" + } + ], + "children": [ + { + "contents": { + "changes": [], + "children": [ + { + "contents": { + "changes": [ + { + "contents": { "contents": { - "contents": { - "fullName": "a.definition.at.path1", - "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", - "rendered": { - "bestTermName": "path1", - "defnTermTag": "Plain", - "signature": [ + "fullName": "a.definition.at.path1", + "hash": "#r303avnmdmja3ch96otiglq37214t43acpr1ikq4hrp5hmcibstipa69frbd6177jvbn28ioc5ii80fc54ecogm4n64dhjvkonrihso", + "rendered": { + "bestTermName": "path1", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path1" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path1" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path1", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path1" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path1", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "a.definition.at.path1" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"definition at path\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "a.definition.at.path1" - ] + "segment": "\"definition at path\"" + } + ], + "tag": "UserObject" }, - "shortName": "path1" + "termDocs": [], + "termNames": [ + "a.definition.at.path1" + ] }, - "tag": "Removed" + "shortName": "path1" }, - "tag": "Plain" + "tag": "Removed" }, - { + "tag": "Plain" + }, + { + "contents": { "contents": { - "contents": { - "fullName": "a.definition.at.path2", - "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", - "rendered": { - "bestTermName": "path2", - "defnTermTag": "Plain", - "signature": [ + "fullName": "a.definition.at.path2", + "hash": "#k43vb9rkd3n4i8g8bbfb31erufbmu6v1f99i587oqsje51thrm1ugdqa7gkjbdvkactuql3cmc00b7oev0glqb2rko48atkuo798mno", + "rendered": { + "bestTermName": "path2", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" + }, + "segment": "a.definition.at.path2" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path2" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.definition.at.path2", - "tag": "HashQualifier" - }, - "segment": "a.definition.at.path2" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.definition.at.path2", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "a.definition.at.path2" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"definition at path2\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "a.definition.at.path2" - ] + "segment": "\"definition at path2\"" + } + ], + "tag": "UserObject" }, - "shortName": "path2" + "termDocs": [], + "termNames": [ + "a.definition.at.path2" + ] }, - "tag": "Removed" + "shortName": "path2" }, - "tag": "Plain" - } - ], - "children": [] - }, - "path": "definition.at" + "tag": "Removed" + }, + "tag": "Plain" + } + ], + "children": [] }, - { - "contents": { - "changes": [ - { + "path": "definition.at" + }, + { + "contents": { + "changes": [ + { + "contents": { "contents": { - "contents": { - "fullName": "a.different.path", - "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", - "rendered": { - "bestTermName": "path", - "defnTermTag": "Plain", - "signature": [ + "fullName": "a.different.path", + "hash": "#83be375arg68mqk26bu12elka6fb6mvq6cec92un1p1t5kulhh6672qlnego952pp7h4lfl7mq3crithvtvo3col9mfc8vurbnb8hvo", + "rendered": { + "bestTermName": "path", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "TypeReference" + }, + "segment": "Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" + }, + "segment": "a.different.path" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" + }, + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "TypeReference" }, "segment": "Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" - }, - "segment": "a.different.path" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "TypeReference" - }, - "segment": "Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "a.different.path", - "tag": "HashQualifier" - }, - "segment": "a.different.path" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "a.different.path", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "a.different.path" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"definition at different path\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "a.different.path" - ] + "segment": "\"definition at different path\"" + } + ], + "tag": "UserObject" }, - "shortName": "path" + "termDocs": [], + "termNames": [ + "a.different.path" + ] }, - "tag": "Removed" + "shortName": "path" }, - "tag": "Plain" - } - ], - "children": [] - }, - "path": "different" - } - ] - }, - "path": "a" - } - ] - }, - "libdeps": [] + "tag": "Removed" + }, + "tag": "Plain" + } + ], + "children": [] + }, + "path": "different" + } + ] + }, + "path": "a" + } + ] }, - "diffKind": "ok" + "libdeps": [] }, + "diffKind": "ok", "newRef": "diff-end", "newRefHash": "#f2bjgi4tm53bf6dcfcukt5a6as3ktlrbiacnqq81nco8i4g7dg6pt14vmc1b7ulsb7rt683qjt2rvg9u92uo5mk1gaqgo8cl30umep8", "oldRef": "diff-start", diff --git a/transcripts/share-apis/contributions/merged-contribution-diff.json b/transcripts/share-apis/contributions/merged-contribution-diff.json index 12eb1d5a..2f176c32 100644 --- a/transcripts/share-apis/contributions/merged-contribution-diff.json +++ b/transcripts/share-apis/contributions/merged-contribution-diff.json @@ -1,258 +1,256 @@ { "body": { "diff": { - "diff": { - "defns": { - "changes": [ - { + "defns": { + "changes": [ + { + "contents": { "contents": { - "contents": { + "diff": { "diff": { "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": "term" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" + "segment": "##Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "\"start\"" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": null, - "segment": " " - } - ] + "segment": "\"feature-one\"" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"start\"" - } - ] + "segment": "term" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"feature-one\"" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "\"start\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + }, + "right": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "term" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"start\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - }, - "right": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"feature-one\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - } - }, - "fullName": "term", - "newHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", - "newTag": "Plain", - "oldHash": "#rhaja5f1cv52a3h2sook0mnagjn62dvm0e66auh1o741bn1qc0fefjlsqqc8mgar0nlui5fdia8ji7j3fbpejdv4dgb3vlh6bq4q4b8", - "oldTag": "Plain", - "shortName": "term" + "segment": "\"feature-one\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + } }, - "tag": "Updated" + "fullName": "term", + "newHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", + "newTag": "Plain", + "oldHash": "#rhaja5f1cv52a3h2sook0mnagjn62dvm0e66auh1o741bn1qc0fefjlsqqc8mgar0nlui5fdia8ji7j3fbpejdv4dgb3vlh6bq4q4b8", + "oldTag": "Plain", + "shortName": "term" }, - "tag": "Plain" - } - ], - "children": [] - }, - "libdeps": [] + "tag": "Updated" + }, + "tag": "Plain" + } + ], + "children": [] }, - "diffKind": "ok" + "libdeps": [] }, + "diffKind": "ok", "newRef": "feature-one", "newRefHash": "#7shvkj0gn9mfne1pemp3oudmo23vio4d8ualvbah6avr7m5471rssu9cd4o6i4pn91bgc62vgnm0oper0itgtmopqmff7c0b40ui1s0", "oldRef": "main", diff --git a/transcripts/share-apis/contributions/transitive-contribution-diff.json b/transcripts/share-apis/contributions/transitive-contribution-diff.json index 98aa28de..9b42a415 100644 --- a/transcripts/share-apis/contributions/transitive-contribution-diff.json +++ b/transcripts/share-apis/contributions/transitive-contribution-diff.json @@ -1,258 +1,256 @@ { "body": { "diff": { - "diff": { - "defns": { - "changes": [ - { + "defns": { + "changes": [ + { + "contents": { "contents": { - "contents": { + "diff": { "diff": { "diff": { - "diff": { - "contents": [ - { - "diffTag": "both", - "elements": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + "contents": [ + { + "diffTag": "both", + "elements": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" + "segment": "term" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": null, - "segment": " " + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" + "segment": "##Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + } + ] + }, + { + "diffTag": "old", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "\"feature-one\"" + } + ] + }, + { + "diffTag": "new", + "elements": [ + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": null, - "segment": " " - } - ] + "segment": "\"feature-two\"" + } + ] + } + ], + "tag": "UserObject" + }, + "diffKind": "diff" + }, + "left": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "diffTag": "old", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"feature-one\"" - } - ] + "segment": "term" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "diffTag": "new", - "elements": [ - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"feature-two\"" - } - ] - } - ], - "tag": "UserObject" - }, - "diffKind": "diff" - }, - "left": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": "\n" + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "\"feature-one\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + }, + "right": { + "bestTermName": "term", + "defnTermTag": "Plain", + "signature": [ + { + "annotation": { + "contents": "##Text", + "tag": "HashQualifier" + }, + "segment": "##Text" + } + ], + "termDefinition": { + "contents": [ + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": null, - "segment": " " + "segment": "term" + }, + { + "annotation": { + "tag": "TypeAscriptionColon" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"feature-one\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - }, - "right": { - "bestTermName": "term", - "defnTermTag": "Plain", - "signature": [ + "segment": " :" + }, + { + "annotation": null, + "segment": " " + }, { "annotation": { "contents": "##Text", "tag": "HashQualifier" }, "segment": "##Text" - } - ], - "termDefinition": { - "contents": [ - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" - }, - { - "annotation": { - "tag": "TypeAscriptionColon" - }, - "segment": " :" - }, - { - "annotation": null, - "segment": " " - }, - { - "annotation": { - "contents": "##Text", - "tag": "HashQualifier" - }, - "segment": "##Text" - }, - { - "annotation": null, - "segment": "\n" - }, - { - "annotation": { - "contents": "term", - "tag": "HashQualifier" - }, - "segment": "term" + }, + { + "annotation": null, + "segment": "\n" + }, + { + "annotation": { + "contents": "term", + "tag": "HashQualifier" }, - { - "annotation": { - "tag": "BindingEquals" - }, - "segment": " =" + "segment": "term" + }, + { + "annotation": { + "tag": "BindingEquals" }, - { - "annotation": null, - "segment": " " + "segment": " =" + }, + { + "annotation": null, + "segment": " " + }, + { + "annotation": { + "tag": "TextLiteral" }, - { - "annotation": { - "tag": "TextLiteral" - }, - "segment": "\"feature-two\"" - } - ], - "tag": "UserObject" - }, - "termDocs": [], - "termNames": [ - "term" - ] - } - }, - "fullName": "term", - "newHash": "#918iukm79ii0jll0m3qtsrcqjp1sqe5rdpf1kochqp52a52s9ciil7mu6m3t4l39pdk60imhj5be1d9rat2lgdmr6u0jn93v7v8o6rg", - "newTag": "Plain", - "oldHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", - "oldTag": "Plain", - "shortName": "term" + "segment": "\"feature-two\"" + } + ], + "tag": "UserObject" + }, + "termDocs": [], + "termNames": [ + "term" + ] + } }, - "tag": "Updated" + "fullName": "term", + "newHash": "#918iukm79ii0jll0m3qtsrcqjp1sqe5rdpf1kochqp52a52s9ciil7mu6m3t4l39pdk60imhj5be1d9rat2lgdmr6u0jn93v7v8o6rg", + "newTag": "Plain", + "oldHash": "#t8aquv2oldk8euc6uveu227hiv76tlic78h607s2nr47mruvocg1oq147b4jf8l850qj2jl37n37ohned32c4ag97mq22cvhl0sbbfo", + "oldTag": "Plain", + "shortName": "term" }, - "tag": "Plain" - } - ], - "children": [] - }, - "libdeps": [] + "tag": "Updated" + }, + "tag": "Plain" + } + ], + "children": [] }, - "diffKind": "ok" + "libdeps": [] }, + "diffKind": "ok", "newRef": "feature-two", "newRefHash": "#ktjspqi8s5ngg129a6lt7i9kd488isfoq8hqmsv54f327de28dq9u0n1dp1vlbgs8jdc6bqss3h46ep9241405ml19nr0gekel56pig", "oldRef": "main", From 1fb060253b321679d0783c5b9da5aa89411f0f04 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Mon, 28 Apr 2025 12:24:53 -0400 Subject: [PATCH 09/16] hydrate terms with more parallelism --- src/Share/Codebase.hs | 23 +++-- src/Share/NamespaceDiffs.hs | 26 +++-- src/Share/Postgres.hs | 18 ++++ src/Share/Postgres/Causal/Queries.hs | 1 + src/Share/Postgres/Definitions/Queries.hs | 114 +++++++++++++++------- src/Share/Postgres/Hashes/Queries.hs | 25 +++++ src/Share/Postgres/NameLookups/Ops.hs | 10 +- 7 files changed, 163 insertions(+), 54 deletions(-) diff --git a/src/Share/Codebase.hs b/src/Share/Codebase.hs index a9c36a90..d69138f9 100644 --- a/src/Share/Codebase.hs +++ b/src/Share/Codebase.hs @@ -67,6 +67,9 @@ module Share.Codebase LCQ.ensureLooseCodeRootHash, setLooseCodeRoot, + -- * Conversions + convertTerm2to1, + -- * Utilities cachedCodebaseResponse, ) @@ -111,6 +114,8 @@ import U.Codebase.Causal qualified as Causal import U.Codebase.Decl qualified as V2 import U.Codebase.Reference qualified as V2 import U.Codebase.Referent qualified as V2 +import U.Codebase.Sqlite.Symbol qualified as V2 +import U.Codebase.Term qualified as V2.Term import Unison.Builtin qualified as Builtin import Unison.Builtin qualified as Builtins import Unison.Codebase.CodeLookup qualified as CL @@ -119,9 +124,11 @@ import Unison.Codebase.SqliteCodebase.Conversions qualified as Cv import Unison.ConstructorType qualified as CT import Unison.DataDeclaration qualified as DD import Unison.DataDeclaration qualified as V1 +import Unison.Hash (Hash) import Unison.Parser.Ann import Unison.Parser.Ann qualified as Ann import Unison.Prelude (askUnliftIO) +import Unison.Reference (TermReferenceId) import Unison.Reference qualified as Reference import Unison.Reference qualified as V1 import Unison.Referent qualified as V1 @@ -261,20 +268,24 @@ cachedCodebaseResponse authzReceipt codebaseOwner endpointName providedCachePara codebaseViewCacheKey = IDs.toText (codebaseOwnerUserId codebaseOwner) -- | Load a term and its type. -loadTerm :: Reference.Id -> CodebaseM e (Maybe (V1.Term Symbol Ann, V1.Type Symbol Ann)) +loadTerm :: TermReferenceId -> CodebaseM e (Maybe (V1.Term Symbol Ann, V1.Type Symbol Ann)) loadTerm refId = do codebaseUser <- asks codebaseOwner lift $ loadTermForCodeLookup codebaseUser refId -- | Load a term and its type. -loadTermForCodeLookup :: UserId -> Reference.Id -> PG.Transaction e (Maybe (V1.Term Symbol Ann, V1.Type Symbol Ann)) +loadTermForCodeLookup :: UserId -> TermReferenceId -> PG.Transaction e (Maybe (V1.Term Symbol Ann, V1.Type Symbol Ann)) loadTermForCodeLookup codebaseUser refId@(Reference.Id h _) = runMaybeT $ do (v2Term, v2Type) <- MaybeT $ DefnQ.loadTerm codebaseUser refId - v1Term <- Cv.term2to1 h (lift . expectDeclKind) v2Term + convertTerm2to1 h v2Term v2Type + +convertTerm2to1 :: (PG.QueryM m) => Hash -> V2.Term.Term V2.Symbol -> V2.Term.Type V2.Symbol -> m (V1.Term Symbol Ann, V1.Type Symbol Ann) +convertTerm2to1 h v2Term v2Type = do + v1Term <- Cv.term2to1 h expectDeclKind v2Term let v1Type = Cv.ttype2to1 v2Type pure (v1Term, v1Type) -expectTerm :: Reference.Id -> CodebaseM e (V1.Term Symbol Ann, V1.Type Symbol Ann) +expectTerm :: TermReferenceId -> CodebaseM e (V1.Term Symbol Ann, V1.Type Symbol Ann) expectTerm refId = loadTerm refId `whenNothingM` lift (unrecoverableError (MissingTerm refId)) -- | Load the type of a term. @@ -308,7 +319,7 @@ expectTypeOfReferents trav s = do s & trav %%~ expectTypeOfReferent expectDeclKind :: (PG.QueryM m) => Reference.TypeReference -> m CT.ConstructorType -expectDeclKind r = loadDeclKind r `whenNothingM` (unrecoverableError (InternalServerError "missing-decl-kind" $ "Couldn't find the decl kind of " <> tShow r)) +expectDeclKind r = loadDeclKind r `whenNothingM` unrecoverableError (DefnQ.missingDeclKindError r) expectDeclKindsOf :: (PG.QueryM m) => Traversal s t Reference.TypeReference CT.ConstructorType -> s -> m t expectDeclKindsOf trav s = do @@ -316,7 +327,7 @@ expectDeclKindsOf trav s = do & unsafePartsOf trav %%~ \refs -> do results <- loadDeclKindsOf traversed refs for (zip refs results) \case - (r, Nothing) -> unrecoverableError (InternalServerError "missing-decl-kind" $ "Couldn't find the decl kind of " <> tShow r) + (r, Nothing) -> unrecoverableError (DefnQ.missingDeclKindError r) (_, Just ct) -> pure ct loadDeclKind :: (PG.QueryM m) => V2.TypeReference -> m (Maybe CT.ConstructorType) diff --git a/src/Share/NamespaceDiffs.hs b/src/Share/NamespaceDiffs.hs index 7e940dc0..a30caf22 100644 --- a/src/Share/NamespaceDiffs.hs +++ b/src/Share/NamespaceDiffs.hs @@ -49,6 +49,7 @@ import Servant (err400, err404, err500) import Share.Codebase qualified as Codebase import Share.Names.Postgres qualified as PGNames import Share.Postgres qualified as PG +import Share.Postgres.Definitions.Queries qualified as DefnsQ import Share.Postgres.IDs (BranchHashId) import Share.Postgres.NameLookups.Ops qualified as NL import Share.Postgres.NameLookups.Types (NameLookupReceipt) @@ -623,14 +624,23 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)) (TypeReferenceId, Decl Symbol Ann) ) <- do - let hydrateTerm :: + let hydrateTerms :: Codebase.CodebaseEnv -> - TermReferenceId -> - PG.Transaction e (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)) - hydrateTerm codebaseEnv ref = - Codebase.codebaseMToTransaction codebaseEnv do - term <- Codebase.expectTerm ref - pure (ref, term) + BiMultimap Referent Name -> + PG.Transaction e (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))) + hydrateTerms codebaseEnv termReferents = do + let codebaseUser = Codebase.codebaseOwner codebaseEnv + let termReferenceIds = Map.mapMaybe Referent.toTermReferenceId (BiMultimap.range termReferents) + termIds <- + PG.pFor termReferenceIds \refId -> + (refId,) <$> DefnsQ.pipelinedExpectTermId refId + v2Terms <- + PG.pFor termIds \(refId, termId) -> + (refId,) <$> DefnsQ.pipelinedExpectTermById codebaseUser refId termId + v1Terms <- + for v2Terms \(refId, (term, typ)) -> + (refId,) <$> Codebase.convertTerm2to1 (Reference.idToHash refId) term typ + pure v1Terms hydrateType :: Codebase.CodebaseEnv -> TypeReferenceId -> @@ -651,7 +661,7 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = ) f codebaseEnv = bitraverse - (traverse (hydrateTerm codebaseEnv) . Map.mapMaybe Referent.toTermReferenceId . BiMultimap.range) + (hydrateTerms codebaseEnv) (traverse (hydrateType codebaseEnv) . Map.mapMaybe Reference.toId . BiMultimap.range) let -- Here we assume that the LCA is in the same codebase as Alice. diff --git a/src/Share/Postgres.hs b/src/Share/Postgres.hs index ab038dff..a472393c 100644 --- a/src/Share/Postgres.hs +++ b/src/Share/Postgres.hs @@ -44,6 +44,8 @@ module Share.Postgres unliftSession, defaultIsolationLevel, pipelined, + pEitherMap, + pUnrecoverableEitherMap, pFor, pFor_, @@ -129,6 +131,22 @@ newtype Pipeline e a = Pipeline {unPipeline :: Hasql.Pipeline.Pipeline (Either ( pipelined :: Pipeline e a -> Transaction e a pipelined p = Transaction (Hasql.pipeline (unPipeline p)) +-- | Like fmap, but the provided function can throw a recoverable error by returning 'Left'. +pEitherMap :: (a -> Either e b) -> Pipeline e a -> Pipeline e b +pEitherMap f (Pipeline p) = + Pipeline $ + p <&> \case + Right x -> mapLeft Err (f x) + Left e -> Left e + +-- | Like 'pEitherMap', but for throwing unrecoverable errors. +pUnrecoverableEitherMap :: (Loggable e, Show e, ToServerError e) => (a -> Either e b) -> Pipeline e' a -> Pipeline e' b +pUnrecoverableEitherMap f (Pipeline p) = + Pipeline $ + p <&> \case + Right x -> mapLeft (Unrecoverable . someServerError) (f x) + Left e -> Left e + pFor :: (Traversable f) => f a -> (a -> Pipeline e b) -> Transaction e (f b) pFor f p = pipelined $ for f p diff --git a/src/Share/Postgres/Causal/Queries.hs b/src/Share/Postgres/Causal/Queries.hs index 8cac1104..405b564f 100644 --- a/src/Share/Postgres/Causal/Queries.hs +++ b/src/Share/Postgres/Causal/Queries.hs @@ -20,6 +20,7 @@ module Share.Postgres.Causal.Queries expectNamespaceStatsOf, expectNamespaceHashByCausalHash, HashQ.expectNamespaceIdsByCausalIdsOf, + HashQ.pipelinedExpectNamespaceIdsByCausalIdsOf, importAccessibleCausals, importCausalIntoCodebase, hashCausal, diff --git a/src/Share/Postgres/Definitions/Queries.hs b/src/Share/Postgres/Definitions/Queries.hs index ef3666c6..c5dbc2fc 100644 --- a/src/Share/Postgres/Definitions/Queries.hs +++ b/src/Share/Postgres/Definitions/Queries.hs @@ -3,6 +3,8 @@ module Share.Postgres.Definitions.Queries ( loadTerm, expectTerm, + pipelinedExpectTermId, + pipelinedExpectTermById, saveTermComponent, saveEncodedTermComponent, loadTermComponent, @@ -31,6 +33,10 @@ module Share.Postgres.Definitions.Queries -- * For Migrations saveSerializedComponent, + + -- * Errors + expectedTermError, + missingDeclKindError, ) where @@ -81,7 +87,7 @@ import Unison.ConstructorType qualified as CT import Unison.Hash (Hash) import Unison.Hash32 (Hash32) import Unison.Hash32 qualified as Hash32 -import Unison.Reference (Reference, TypeReference) +import Unison.Reference (Reference, TermReferenceId, TypeReference, TypeReferenceId) import Unison.Reference qualified as Reference import Unison.Reference qualified as V1Reference import Unison.Referent qualified as V1Referent @@ -129,26 +135,37 @@ instance Logging.Loggable DefinitionQueryError where -- | This isn't in CodebaseM so that we can run it in a normal transaction to build the Code -- Lookup. -loadTerm :: UserId -> Reference.Id -> PG.Transaction e (Maybe (V2.Term Symbol, V2.Type Symbol)) -loadTerm userId (Reference.Id compHash (pgComponentIndex -> compIndex)) = runMaybeT $ do - termId <- - MaybeT $ - query1Col - [sql| - SELECT term.id - FROM terms term - JOIN component_hashes ON term.component_hash_id = component_hashes.id - WHERE component_hashes.base32 = #{compHash} - AND term.component_index = #{compIndex} - |] +loadTerm :: UserId -> TermReferenceId -> PG.Transaction e (Maybe (V2.Term Symbol, V2.Type Symbol)) +loadTerm userId refId = runMaybeT do + termId <- MaybeT $ loadTermId refId MaybeT $ loadTermById userId termId +loadTermId :: (QueryA m) => TermReferenceId -> m (Maybe TermId) +loadTermId (Reference.Id compHash (pgComponentIndex -> compIndex)) = + query1Col + [sql| + SELECT term.id + FROM terms term + JOIN component_hashes ON term.component_hash_id = component_hashes.id + WHERE component_hashes.base32 = #{compHash} + AND term.component_index = #{compIndex} + |] + +pipelinedExpectTermId :: TermReferenceId -> PG.Pipeline e TermId +pipelinedExpectTermId refId = + pUnrecoverableEitherMap + ( \case + Nothing -> Left (expectedTermError refId) + Just termId -> Right termId + ) + (loadTermId refId) + expectTerm :: UserId -> Reference.Id -> PG.Transaction e (V2.Term Symbol, V2.Type Symbol) expectTerm userId refId = do mayTerm <- loadTerm userId refId case mayTerm of Just term -> pure term - Nothing -> unrecoverableError $ InternalServerError "expected-term" (ExpectedTermNotFound refId) + Nothing -> unrecoverableError $ expectedTermError refId resolveComponentHash :: ComponentRef -> CodebaseM e (ComponentHash, ComponentHashId) resolveComponentHash = \case @@ -279,25 +296,44 @@ expectTypeComponent componentRef = do -- | This isn't in CodebaseM so that we can run it in a normal transaction to build the Code -- Lookup. -loadTermById :: (QueryM m) => UserId -> TermId -> m (Maybe (V2.Term Symbol, V2.Type Symbol)) -loadTermById codebaseUser termId = runMaybeT $ do - (TermComponentElement trm typ) <- - MaybeT $ - query1Col - [sql| - SELECT bytes.bytes - FROM sandboxed_terms sandboxed - JOIN bytes ON sandboxed.bytes_id = bytes.id - WHERE sandboxed.user_id = #{codebaseUser} - AND sandboxed.term_id = #{termId} - |] - textLookup <- lift $ termLocalTextReferences termId - defnLookup <- lift $ termLocalComponentReferences termId - let localIds :: ResolvedLocalIds - localIds = LocalIds.LocalIds {textLookup = Vector.fromList textLookup, defnLookup = Vector.fromList defnLookup} - pure $ s2cTermWithType (localIds, trm, typ) +loadTermById :: (QueryA m) => UserId -> TermId -> m (Maybe (V2.Term Symbol, V2.Type Symbol)) +loadTermById codebaseUser termId = do + ( \maybeTermComponentElement localIds -> + maybeTermComponentElement <&> \(TermComponentElement trm typ) -> + s2cTermWithType (localIds, trm, typ) + ) + <$> loadTermComponentElementByTermId codebaseUser termId + <*> loadResolvedLocalIdsByTermId termId + +pipelinedExpectTermById :: UserId -> TermReferenceId -> TermId -> Pipeline e (V2.Term Symbol, V2.Type Symbol) +pipelinedExpectTermById userId refId termId = + pUnrecoverableEitherMap + ( \case + Nothing -> Left (expectedTermError refId) + Just term -> Right term + ) + (loadTermById userId termId) + +loadTermComponentElementByTermId :: (QueryA m) => UserId -> TermId -> m (Maybe TermComponentElement) +loadTermComponentElementByTermId codebaseUser termId = + query1Col + [sql| + SELECT bytes.bytes + FROM sandboxed_terms sandboxed + JOIN bytes ON sandboxed.bytes_id = bytes.id + WHERE sandboxed.user_id = #{codebaseUser} + AND sandboxed.term_id = #{termId} + |] + +loadResolvedLocalIdsByTermId :: (QueryA m) => TermId -> m ResolvedLocalIds +loadResolvedLocalIdsByTermId termId = + ( \textLookup defnLookup -> + LocalIds.LocalIds {textLookup = Vector.fromList textLookup, defnLookup = Vector.fromList defnLookup} + ) + <$> termLocalTextReferences termId + <*> termLocalComponentReferences termId -termLocalTextReferences :: (QueryM m) => TermId -> m [Text] +termLocalTextReferences :: (QueryA m) => TermId -> m [Text] termLocalTextReferences termId = queryListCol [sql| @@ -308,7 +344,7 @@ termLocalTextReferences termId = ORDER BY local_index ASC |] -termLocalComponentReferences :: (QueryM m) => TermId -> m [ComponentHash] +termLocalComponentReferences :: (QueryA m) => TermId -> m [ComponentHash] termLocalComponentReferences termId = queryListCol [sql| @@ -351,10 +387,10 @@ resolveConstructorTypeLocalIds (LocalIds.LocalIds {textLookup, defnLookup}) = substText i = textLookup ^?! ix (fromIntegral i) substHash i = unComponentHash $ (defnLookup ^?! ix (fromIntegral i)) -loadDeclKind :: (PG.QueryM m) => Reference.Id -> m (Maybe CT.ConstructorType) +loadDeclKind :: (PG.QueryA m) => TypeReferenceId -> m (Maybe CT.ConstructorType) loadDeclKind = loadDeclKindsOf id -loadDeclKindsOf :: (PG.QueryM m) => Traversal s t Reference.Id (Maybe CT.ConstructorType) -> s -> m t +loadDeclKindsOf :: (PG.QueryA m) => Traversal s t TypeReferenceId (Maybe CT.ConstructorType) -> s -> m t loadDeclKindsOf trav s = s & unsafePartsOf trav %%~ \refIds -> do @@ -1167,3 +1203,11 @@ saveSerializedComponent chId (CBORBytes bytes) = do VALUES (#{codebaseOwnerUserId}, #{chId}, #{bytesId}) ON CONFLICT DO NOTHING |] + +expectedTermError :: TermReferenceId -> InternalServerError DefinitionQueryError +expectedTermError refId = + InternalServerError "expected-term" (ExpectedTermNotFound refId) + +missingDeclKindError :: TypeReference -> InternalServerError Text +missingDeclKindError r = + InternalServerError "missing-decl-kind" $ "Couldn't find the decl kind of " <> tShow r diff --git a/src/Share/Postgres/Hashes/Queries.hs b/src/Share/Postgres/Hashes/Queries.hs index 6d422a0a..d9d82ed2 100644 --- a/src/Share/Postgres/Hashes/Queries.hs +++ b/src/Share/Postgres/Hashes/Queries.hs @@ -29,6 +29,7 @@ module Share.Postgres.Hashes.Queries loadCausalIdByHash, expectCausalIdByHash, expectNamespaceIdsByCausalIdsOf, + pipelinedExpectNamespaceIdsByCausalIdsOf, expectNamespaceHashesByNamespaceHashIdsOf, isComponentHashAllowedToBeMismatched, isCausalHashAllowedToBeMismatched, @@ -304,6 +305,30 @@ expectNamespaceIdsByCausalIdsOf trav s = do then unrecoverableError . MissingExpectedEntity $ "expectNamespaceIdsByCausalIdsOf: Expected to get the same number of results as causal ids. " <> tShow causalIds else pure results +-- | Mitchell says: this could/should just have replaced 'expectNamespaceIdsByCausalIdsOf', but that function has +-- many callers, so having two temporarily eases the transition. +pipelinedExpectNamespaceIdsByCausalIdsOf :: Traversal s t CausalId BranchHashId -> s -> Pipeline e t +pipelinedExpectNamespaceIdsByCausalIdsOf trav s = do + s + & unsafePartsOf trav %%~ \causalIds -> + let causalIdsTable = ordered causalIds + in pUnrecoverableEitherMap + ( \results -> + if length results /= length causalIds + then Left (MissingExpectedEntity $ "expectNamespaceIdsByCausalIdsOf: Expected to get the same number of results as causal ids. " <> tShow causalIds) + else Right results + ) + ( queryListCol @(BranchHashId) + [sql| WITH causal_ids(ord, causal_id) AS ( + SELECT ord, causal_id FROM ^{toTable causalIdsTable} as t(ord, causal_id) + ) + SELECT c.namespace_hash_id + FROM causal_ids cid + JOIN causals c ON cid.causal_id = c.id + ORDER BY cid.ord + |] + ) + expectNamespaceHashesByNamespaceHashIdsOf :: (HasCallStack, QueryM m) => Traversal s t BranchHashId BranchHash -> s -> m t expectNamespaceHashesByNamespaceHashIdsOf trav s = do s diff --git a/src/Share/Postgres/NameLookups/Ops.hs b/src/Share/Postgres/NameLookups/Ops.hs index 953236c2..4f7dfa6c 100644 --- a/src/Share/Postgres/NameLookups/Ops.hs +++ b/src/Share/Postgres/NameLookups/Ops.hs @@ -20,7 +20,7 @@ import Control.Lens import Control.Monad.Trans.Maybe import Data.List.NonEmpty qualified as NonEmpty import Data.Set qualified as Set -import Share.Postgres (QueryM) +import Share.Postgres (QueryA, QueryM) import Share.Postgres qualified as PG import Share.Postgres.Cursors qualified as Cursor import Share.Postgres.Hashes.Queries qualified as HashQ @@ -188,10 +188,10 @@ deleteNameLookupsExceptFor reachable = do bhIds <- for (Set.toList reachable) HashQ.ensureBranchHashId Q.deleteNameLookupsExceptFor bhIds -ensureNameLookupForBranchId :: (QueryM m) => BranchHashId -> m NameLookupReceipt -ensureNameLookupForBranchId branchHashId = do - PG.execute_ [PG.sql| SELECT ensure_name_lookup(#{branchHashId}) |] - pure $ UnsafeNameLookupReceipt +ensureNameLookupForBranchId :: (QueryA m) => BranchHashId -> m NameLookupReceipt +ensureNameLookupForBranchId branchHashId = + UnsafeNameLookupReceipt + <$ PG.execute_ [PG.sql| SELECT ensure_name_lookup(#{branchHashId}) |] -- | Build a 'Names' for all definitions within the given root, without any dependencies. -- Note: This loads everything into memory at once, so avoid this and prefer streaming when possible. From d1cb4d46c6528013a83322a768259e98db1dc77c Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Mon, 28 Apr 2025 12:25:42 -0400 Subject: [PATCH 10/16] tweak indentation --- src/Share/Postgres/Hashes/Queries.hs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Share/Postgres/Hashes/Queries.hs b/src/Share/Postgres/Hashes/Queries.hs index d9d82ed2..0b452692 100644 --- a/src/Share/Postgres/Hashes/Queries.hs +++ b/src/Share/Postgres/Hashes/Queries.hs @@ -318,15 +318,16 @@ pipelinedExpectNamespaceIdsByCausalIdsOf trav s = do then Left (MissingExpectedEntity $ "expectNamespaceIdsByCausalIdsOf: Expected to get the same number of results as causal ids. " <> tShow causalIds) else Right results ) - ( queryListCol @(BranchHashId) - [sql| WITH causal_ids(ord, causal_id) AS ( - SELECT ord, causal_id FROM ^{toTable causalIdsTable} as t(ord, causal_id) - ) - SELECT c.namespace_hash_id - FROM causal_ids cid - JOIN causals c ON cid.causal_id = c.id - ORDER BY cid.ord - |] + ( queryListCol @BranchHashId + [sql| + WITH causal_ids(ord, causal_id) AS ( + SELECT ord, causal_id FROM ^{toTable causalIdsTable} as t(ord, causal_id) + ) + SELECT c.namespace_hash_id + FROM causal_ids cid + JOIN causals c ON cid.causal_id = c.id + ORDER BY cid.ord + |] ) expectNamespaceHashesByNamespaceHashIdsOf :: (HasCallStack, QueryM m) => Traversal s t BranchHashId BranchHash -> s -> m t From ffc243cefd8fcdf51a0db2a8c3aade1276e8cada Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Mon, 28 Apr 2025 16:06:05 -0400 Subject: [PATCH 11/16] fetch type decls in parallel --- src/Share/NamespaceDiffs.hs | 35 +++--- src/Share/Postgres/Definitions/Queries.hs | 136 ++++++++++++---------- 2 files changed, 93 insertions(+), 78 deletions(-) diff --git a/src/Share/NamespaceDiffs.hs b/src/Share/NamespaceDiffs.hs index a30caf22..c3fdf0e8 100644 --- a/src/Share/NamespaceDiffs.hs +++ b/src/Share/NamespaceDiffs.hs @@ -47,6 +47,7 @@ import Data.Set.NonEmpty (NESet) import Data.Set.NonEmpty qualified as NESet import Servant (err400, err404, err500) import Share.Codebase qualified as Codebase +import Share.IDs (UserId) import Share.Names.Postgres qualified as PGNames import Share.Postgres qualified as PG import Share.Postgres.Definitions.Queries qualified as DefnsQ @@ -59,6 +60,7 @@ import Share.Utils.Logging qualified as Logging import Share.Web.Errors import Unison.Codebase.Path (Path) import Unison.Codebase.Path qualified as Path +import Unison.Codebase.SqliteCodebase.Conversions qualified as Cv import Unison.DataDeclaration (Decl) import Unison.LabeledDependency (LabeledDependency) import Unison.Merge (DiffOp, EitherWay, Mergeblob0, Mergeblob1, ThreeWay (..), TwoOrThreeWay (..), TwoWay (..)) @@ -625,11 +627,10 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = (TypeReferenceId, Decl Symbol Ann) ) <- do let hydrateTerms :: - Codebase.CodebaseEnv -> + UserId -> BiMultimap Referent Name -> PG.Transaction e (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))) - hydrateTerms codebaseEnv termReferents = do - let codebaseUser = Codebase.codebaseOwner codebaseEnv + hydrateTerms codebaseUser termReferents = do let termReferenceIds = Map.mapMaybe Referent.toTermReferenceId (BiMultimap.range termReferents) termIds <- PG.pFor termReferenceIds \refId -> @@ -641,14 +642,21 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = for v2Terms \(refId, (term, typ)) -> (refId,) <$> Codebase.convertTerm2to1 (Reference.idToHash refId) term typ pure v1Terms - hydrateType :: - Codebase.CodebaseEnv -> - TypeReferenceId -> - PG.Transaction e (TypeReferenceId, Decl Symbol Ann) - hydrateType codebaseEnv ref = - Codebase.codebaseMToTransaction codebaseEnv do - type_ <- Codebase.expectTypeDeclaration ref - pure (ref, type_) + hydrateTypes :: + UserId -> + BiMultimap TypeReference Name -> + PG.Transaction e (Map Name (TypeReferenceId, Decl Symbol Ann)) + hydrateTypes codebaseUser typeReferences = do + let typeReferenceIds = Map.mapMaybe Reference.toId (BiMultimap.range typeReferences) + typeIds <- + PG.pFor typeReferenceIds \refId -> + (refId,) <$> DefnsQ.pipelinedExpectTypeComponentElementAndTypeId codebaseUser refId + v1Decls <- + PG.pFor typeIds \(refId, typeId) -> + DefnsQ.loadDeclByTypeComponentElementAndTypeId typeId <&> \v2Decl -> + let v1Decl = Cv.decl2to1 (Reference.idToHash refId) v2Decl + in (refId, v1Decl) + pure v1Decls f :: Codebase.CodebaseEnv -> Defns (BiMultimap Referent Name) (BiMultimap TypeReference Name) -> @@ -660,9 +668,8 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = (TypeReferenceId, Decl Symbol Ann) ) f codebaseEnv = - bitraverse - (hydrateTerms codebaseEnv) - (traverse (hydrateType codebaseEnv) . Map.mapMaybe Reference.toId . BiMultimap.range) + let codebaseUser = Codebase.codebaseOwner codebaseEnv + in bitraverse (hydrateTerms codebaseUser) (hydrateTypes codebaseUser) let -- Here we assume that the LCA is in the same codebase as Alice. codebaseEnvs3 :: ThreeWay Codebase.CodebaseEnv diff --git a/src/Share/Postgres/Definitions/Queries.hs b/src/Share/Postgres/Definitions/Queries.hs index c5dbc2fc..b50f8a08 100644 --- a/src/Share/Postgres/Definitions/Queries.hs +++ b/src/Share/Postgres/Definitions/Queries.hs @@ -19,6 +19,8 @@ module Share.Postgres.Definitions.Queries loadDeclKindsOf, loadDecl, expectDecl, + loadDeclByTypeComponentElementAndTypeId, + pipelinedExpectTypeComponentElementAndTypeId, loadCachedEvalResult, saveCachedEvalResult, termReferencesByPrefix, @@ -36,6 +38,7 @@ module Share.Postgres.Definitions.Queries -- * Errors expectedTermError, + expectedTypeError, missingDeclKindError, ) where @@ -47,7 +50,6 @@ import Data.List.NonEmpty qualified as NE import Data.List.NonEmpty qualified as NonEmpty import Data.Set qualified as Set import Data.Text qualified as Text -import Data.Vector (Vector) import Data.Vector qualified as Vector import Servant (err500) import Share.Codebase.Types (CodebaseEnv (..), CodebaseM) @@ -105,9 +107,9 @@ type PgLocalIds = LocalIds.LocalIds' TextId ComponentHashId type ComponentRef = These ComponentHash ComponentHashId data DefinitionQueryError - = ExpectedTermNotFound Reference.Id + = ExpectedTermNotFound TermReferenceId | ExpectedTermComponentNotFound ComponentRef - | ExpectedTypeNotFound Reference.Id + | ExpectedTypeNotFound TypeReferenceId | ExpectedTypeComponentNotFound ComponentRef deriving stock (Show) @@ -247,10 +249,8 @@ expectShareTermComponent componentHashId = do ) `whenNothingM` do lift . unrecoverableError $ InternalServerError "expected-term-component" (ExpectedTermComponentNotFound (That componentHashId)) - second (Hash32.fromHash . unComponentHash) . Share.TermComponent . toList <$> for componentElements \(termId, LocalTermBytes bytes) -> do - textLookup <- lift $ termLocalTextReferences termId - defnLookup <- lift $ termLocalComponentReferences termId - pure (Share.LocalIds {texts = textLookup, hashes = defnLookup}, bytes) + second (Hash32.fromHash . unComponentHash) . Share.TermComponent . toList <$> for componentElements \(termId, LocalTermBytes bytes) -> + (,bytes) <$> termLocalReferences termId where checkElements :: [(TermId, Maybe LocalTermBytes)] -> Maybe (NonEmpty (TermId, LocalTermBytes)) checkElements rows = @@ -277,10 +277,8 @@ expectShareTypeComponent componentHashId = do ) `whenNothingM` do lift . unrecoverableError $ InternalServerError "expected-type-component" (ExpectedTypeComponentNotFound (That componentHashId)) - second (Hash32.fromHash . unComponentHash) . Share.DeclComponent . toList <$> for componentElements \(typeId, LocalTypeBytes bytes) -> do - textLookup <- lift $ typeLocalTextReferences typeId - defnLookup <- lift $ typeLocalComponentReferences typeId - pure (Share.LocalIds {texts = Vector.toList textLookup, hashes = Vector.toList defnLookup}, bytes) + second (Hash32.fromHash . unComponentHash) . Share.DeclComponent . toList <$> for componentElements \(typeId, LocalTypeBytes bytes) -> + (,bytes) <$> typeLocalReferences typeId where checkElements :: [(TypeId, Maybe LocalTypeBytes)] -> Maybe (NonEmpty (TypeId, LocalTypeBytes)) checkElements rows = @@ -298,12 +296,19 @@ expectTypeComponent componentRef = do -- Lookup. loadTermById :: (QueryA m) => UserId -> TermId -> m (Maybe (V2.Term Symbol, V2.Type Symbol)) loadTermById codebaseUser termId = do - ( \maybeTermComponentElement localIds -> + ( \maybeTermComponentElement Share.LocalIds {texts, hashes} -> maybeTermComponentElement <&> \(TermComponentElement trm typ) -> - s2cTermWithType (localIds, trm, typ) + s2cTermWithType + ( LocalIds.LocalIds + { textLookup = Vector.fromList texts, + defnLookup = Vector.fromList hashes + }, + trm, + typ + ) ) <$> loadTermComponentElementByTermId codebaseUser termId - <*> loadResolvedLocalIdsByTermId termId + <*> termLocalReferences termId pipelinedExpectTermById :: UserId -> TermReferenceId -> TermId -> Pipeline e (V2.Term Symbol, V2.Type Symbol) pipelinedExpectTermById userId refId termId = @@ -325,11 +330,9 @@ loadTermComponentElementByTermId codebaseUser termId = AND sandboxed.term_id = #{termId} |] -loadResolvedLocalIdsByTermId :: (QueryA m) => TermId -> m ResolvedLocalIds -loadResolvedLocalIdsByTermId termId = - ( \textLookup defnLookup -> - LocalIds.LocalIds {textLookup = Vector.fromList textLookup, defnLookup = Vector.fromList defnLookup} - ) +termLocalReferences :: (QueryA m) => TermId -> m (Share.LocalIds Text ComponentHash) +termLocalReferences termId = + Share.LocalIds <$> termLocalTextReferences termId <*> termLocalComponentReferences termId @@ -413,50 +416,52 @@ loadDeclKindsOf trav s = -- | This isn't in CodebaseM so that we can run it in a normal transaction to build the Code -- Lookup. -loadDecl :: UserId -> Reference.Id -> PG.Transaction e (Maybe (V2.Decl Symbol)) -loadDecl codebaseUser (Reference.Id compHash (pgComponentIndex -> compIndex)) = runMaybeT $ do - (TypeComponentElement decl, typeId :: TypeId) <- - MaybeT $ - query1Row - [sql| - SELECT bytes.bytes, typ.id - FROM types typ - JOIN component_hashes ON typ.component_hash_id = component_hashes.id - JOIN sandboxed_types sandboxed ON typ.id = sandboxed.type_id - JOIN bytes ON sandboxed.bytes_id = bytes.id - WHERE sandboxed.user_id = #{codebaseUser} - AND component_hashes.base32 = #{compHash} - AND typ.component_index = #{compIndex} - |] - textLookup <- - Vector.fromList - <$> queryListCol - [sql| - SELECT text.text - FROM type_local_text_references - JOIN text ON type_local_text_references.text_id = text.id - WHERE type_id = #{typeId} - ORDER BY local_index ASC - |] - defnLookup <- - Vector.fromList - <$> queryListCol - [sql| - SELECT component_hashes.base32 - FROM type_local_component_references - JOIN component_hashes ON type_local_component_references.component_hash_id = component_hashes.id - WHERE type_id = #{typeId} - ORDER BY local_index ASC - |] - let localIds :: ResolvedLocalIds - localIds = LocalIds.LocalIds {textLookup, defnLookup} +loadDecl :: (QueryM m) => UserId -> TypeReferenceId -> m (Maybe (V2.Decl Symbol)) +loadDecl codebaseUser refId = runMaybeT $ do + (TypeComponentElement decl, typeId :: TypeId) <- MaybeT (loadTypeComponentElementAndTypeId codebaseUser refId) + Share.LocalIds {texts, hashes} <- typeLocalReferences typeId + let localIds = LocalIds.LocalIds {textLookup = Vector.fromList texts, defnLookup = Vector.fromList hashes} pure $ s2cDecl localIds decl -typeLocalTextReferences :: TypeId -> Transaction e (Vector Text) +loadDeclByTypeComponentElementAndTypeId :: QueryA m => (TypeComponentElement, TypeId) -> m (V2.Decl Symbol) +loadDeclByTypeComponentElementAndTypeId (TypeComponentElement decl, typeId) = + typeLocalReferences typeId <&> \Share.LocalIds {texts, hashes} -> + let localIds = LocalIds.LocalIds {textLookup = Vector.fromList texts, defnLookup = Vector.fromList hashes} + in s2cDecl localIds decl + +loadTypeComponentElementAndTypeId :: (QueryA m) => UserId -> TypeReferenceId -> m (Maybe (TypeComponentElement, TypeId)) +loadTypeComponentElementAndTypeId codebaseUser (Reference.Id compHash (pgComponentIndex -> compIndex)) = do + query1Row + [sql| + SELECT bytes.bytes, typ.id + FROM types typ + JOIN component_hashes ON typ.component_hash_id = component_hashes.id + JOIN sandboxed_types sandboxed ON typ.id = sandboxed.type_id + JOIN bytes ON sandboxed.bytes_id = bytes.id + WHERE sandboxed.user_id = #{codebaseUser} + AND component_hashes.base32 = #{compHash} + AND typ.component_index = #{compIndex} + |] + +pipelinedExpectTypeComponentElementAndTypeId :: UserId -> TermReferenceId -> PG.Pipeline e (TypeComponentElement, TypeId) +pipelinedExpectTypeComponentElementAndTypeId codebaseUser refId = + pUnrecoverableEitherMap + ( \case + Nothing -> Left (expectedTypeError refId) + Just decl -> Right decl + ) + (loadTypeComponentElementAndTypeId codebaseUser refId) + +typeLocalReferences :: (QueryA m) => TypeId -> m (Share.LocalIds Text ComponentHash) +typeLocalReferences typeId = + Share.LocalIds + <$> typeLocalTextReferences typeId + <*> typeLocalComponentReferences typeId + +typeLocalTextReferences :: (QueryA m) => TypeId -> m [Text] typeLocalTextReferences typeId = - Vector.fromList - <$> queryListCol - [sql| + queryListCol + [sql| SELECT text.text FROM type_local_text_references JOIN text ON type_local_text_references.text_id = text.id @@ -464,11 +469,10 @@ typeLocalTextReferences typeId = ORDER BY local_index ASC |] -typeLocalComponentReferences :: TypeId -> Transaction e (Vector ComponentHash) +typeLocalComponentReferences :: (QueryA m) => TypeId -> m [ComponentHash] typeLocalComponentReferences typeId = - Vector.fromList - <$> queryListCol - [sql| + queryListCol + [sql| SELECT component_hashes.base32 FROM type_local_component_references JOIN component_hashes ON type_local_component_references.component_hash_id = component_hashes.id @@ -1208,6 +1212,10 @@ expectedTermError :: TermReferenceId -> InternalServerError DefinitionQueryError expectedTermError refId = InternalServerError "expected-term" (ExpectedTermNotFound refId) +expectedTypeError :: TypeReferenceId -> InternalServerError DefinitionQueryError +expectedTypeError refId = + InternalServerError "expected-type" (ExpectedTypeNotFound refId) + missingDeclKindError :: TypeReference -> InternalServerError Text missingDeclKindError r = InternalServerError "missing-decl-kind" $ "Couldn't find the decl kind of " <> tShow r From 169c1e5496c16b2b31954cd2ad69c55668493868 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Thu, 1 May 2025 09:44:50 -0400 Subject: [PATCH 12/16] store namespace diff errors --- sql/2025-04-30-contribution-diff-queue.sql | 13 ++ .../BackgroundJobs/Diffs/ContributionDiffs.hs | 11 +- src/Share/BackgroundJobs/Diffs/Queries.hs | 17 +- src/Share/NamespaceDiffs.hs | 193 +++++++++++++++++- src/Share/Web/Share/Contributions/Impl.hs | 2 +- src/Share/Web/Share/Diffs/Impl.hs | 180 +++------------- src/Share/Web/Share/Diffs/Types.hs | 149 ++------------ src/Share/Web/Share/Projects/Impl.hs | 9 +- .../contribution-diffs/contribution-diff.json | 7 +- .../contribution-diffs/namespace-diff.json | 7 +- .../merged-contribution-diff.json | 7 +- .../transitive-contribution-diff.json | 7 +- 12 files changed, 284 insertions(+), 318 deletions(-) create mode 100644 sql/2025-04-30-contribution-diff-queue.sql diff --git a/sql/2025-04-30-contribution-diff-queue.sql b/sql/2025-04-30-contribution-diff-queue.sql new file mode 100644 index 00000000..c09ac929 --- /dev/null +++ b/sql/2025-04-30-contribution-diff-queue.sql @@ -0,0 +1,13 @@ +-- Drop and re-create the contribution_diff_queue table without a primary key constraint on contribution_id. +-- This allows us to insert redundant rows while a diff is being computed, rather than blocking due to row lock. + +DROP TABLE contribution_diff_queue; + +CREATE TABLE contribution_diff_queue ( + contribution_id UUID REFERENCES contributions(id) ON DELETE CASCADE, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Delete all previously-computed namespace diffs, because the diff payload is different now (we explicitly store +-- errors). +TRUNCATE namespace_diffs; diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 04877506..567621a3 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -14,7 +14,6 @@ import Share.Env qualified as Env import Share.IDs import Share.IDs qualified as IDs import Share.Metrics qualified as Metrics -import Share.NamespaceDiffs (NamespaceDiffError (MissingEntityError)) import Share.Postgres qualified as PG import Share.Postgres.Contributions.Queries qualified as ContributionsQ import Share.Postgres.Notifications qualified as Notif @@ -79,13 +78,13 @@ maybeComputeAndStoreCausalDiff :: AuthZ.AuthZReceipt -> (Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO)) -> ContributionId -> - PG.Transaction NamespaceDiffError Bool + PG.Transaction EntityMissing Bool maybeComputeAndStoreCausalDiff authZReceipt makeRuntime contributionId = do Contribution {bestCommonAncestorCausalId, sourceBranchId = newBranchId, targetBranchId = oldBranchId, projectId} <- - ContributionsQ.contributionById contributionId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "contribution:missing") "Contribution not found") - project <- Q.projectById projectId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "project:missing") "Project not found") - newBranch <- Q.branchById newBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Source branch not found") - oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (MissingEntityError $ EntityMissing (ErrorID "branch:missing") "Target branch not found") + ContributionsQ.contributionById contributionId `whenNothingM` throwError (EntityMissing (ErrorID "contribution:missing") "Contribution not found") + project <- Q.projectById projectId `whenNothingM` throwError (EntityMissing (ErrorID "project:missing") "Project not found") + newBranch <- Q.branchById newBranchId `whenNothingM` throwError (EntityMissing (ErrorID "branch:missing") "Source branch not found") + oldBranch <- Q.branchById oldBranchId `whenNothingM` throwError (EntityMissing (ErrorID "branch:missing") "Target branch not found") let oldCodebase = Codebase.codebaseForProjectBranch authZReceipt project oldBranch let newCodebase = Codebase.codebaseForProjectBranch authZReceipt project newBranch let oldCausal = oldBranch ^. branchCausals_ diff --git a/src/Share/BackgroundJobs/Diffs/Queries.hs b/src/Share/BackgroundJobs/Diffs/Queries.hs index a3b965bf..184e596b 100644 --- a/src/Share/BackgroundJobs/Diffs/Queries.hs +++ b/src/Share/BackgroundJobs/Diffs/Queries.hs @@ -12,16 +12,12 @@ import Unison.Prelude submitContributionToBeDiffed :: (QueryM m) => ContributionId -> m () submitContributionToBeDiffed contributionId = do - result <- - query1Col @Int64 - [sql| - INSERT INTO contribution_diff_queue (contribution_id) - VALUES (#{contributionId}) - ON CONFLICT DO NOTHING - RETURNING 1 - |] - whenJust result \_ -> - Notif.notifyChannel Notif.ContributionDiffChannel + execute_ + [sql| + INSERT INTO contribution_diff_queue (contribution_id) + VALUES (#{contributionId}) + |] + Notif.notifyChannel Notif.ContributionDiffChannel submitContributionsToBeDiffed :: (QueryM m) => Set ContributionId -> m () submitContributionsToBeDiffed contributions = do @@ -32,7 +28,6 @@ submitContributionsToBeDiffed contributions = do ) INSERT INTO contribution_diff_queue (contribution_id) SELECT nc.contribution_id FROM new_contributions nc - ON CONFLICT DO NOTHING |] Notif.notifyChannel Notif.ContributionDiffChannel diff --git a/src/Share/NamespaceDiffs.hs b/src/Share/NamespaceDiffs.hs index c3fdf0e8..9e065056 100644 --- a/src/Share/NamespaceDiffs.hs +++ b/src/Share/NamespaceDiffs.hs @@ -1,7 +1,8 @@ -- | Logic for computing the differerences between two namespaces, -- typically used when showing the differences caused by a contribution. module Share.NamespaceDiffs - ( NamespaceAndLibdepsDiff, + ( NamespaceDiffResult (..), + NamespaceAndLibdepsDiff, GNamespaceAndLibdepsDiff (..), NamespaceTreeDiff, GNamespaceTreeDiff, @@ -35,8 +36,11 @@ where import Control.Comonad.Cofree (Cofree) import Control.Comonad.Cofree qualified as Cofree -import Control.Lens hiding ((:<)) +import Control.Lens hiding ((.=), (:<)) import Control.Monad.Except +import Data.Aeson (ToJSON, (.=)) +import Data.Aeson qualified as Aeson +import Data.Aeson.Types (ToJSON (..)) import Data.Align (Semialign (..)) import Data.Either (partitionEithers) import Data.Foldable qualified as Foldable @@ -51,7 +55,7 @@ import Share.IDs (UserId) import Share.Names.Postgres qualified as PGNames import Share.Postgres qualified as PG import Share.Postgres.Definitions.Queries qualified as DefnsQ -import Share.Postgres.IDs (BranchHashId) +import Share.Postgres.IDs (BranchHash, BranchHashId) import Share.Postgres.NameLookups.Ops qualified as NL import Share.Postgres.NameLookups.Types (NameLookupReceipt) import Share.Postgres.NameLookups.Types qualified as NL @@ -63,9 +67,9 @@ import Unison.Codebase.Path qualified as Path import Unison.Codebase.SqliteCodebase.Conversions qualified as Cv import Unison.DataDeclaration (Decl) import Unison.LabeledDependency (LabeledDependency) -import Unison.Merge (DiffOp, EitherWay, Mergeblob0, Mergeblob1, ThreeWay (..), TwoOrThreeWay (..), TwoWay (..)) +import Unison.Merge (DiffOp, EitherWay, IncoherentDeclReason (..), Mergeblob0, Mergeblob1, ThreeWay (..), TwoOrThreeWay (..), TwoWay (..)) import Unison.Merge qualified as Merge -import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReason) +import Unison.Merge.EitherWay qualified as EitherWay import Unison.Merge.HumanDiffOp (HumanDiffOp (..)) import Unison.Merge.Mergeblob1 qualified as Mergeblob1 import Unison.Merge.ThreeWay qualified as ThreeWay @@ -80,6 +84,8 @@ import Unison.Reference (Reference, TermReferenceId, TypeReference, TypeReferenc import Unison.Reference qualified as Reference import Unison.Referent (Referent) import Unison.Referent qualified as Referent +import Unison.Server.Types (DisplayObjectDiff (..), TermDefinition, TermDefinitionDiff (..), TermTag, TypeDefinition, TypeDefinitionDiff (..), TypeTag) +import Unison.ShortHash (ShortHash) import Unison.Symbol (Symbol) import Unison.Syntax.NameSegment qualified as NameSegment import Unison.Term (Term) @@ -222,6 +228,183 @@ definitionDiffKindRendered_ f = \case RenamedTo r old rendered -> RenamedTo r old <$> f rendered RenamedFrom r old rendered -> RenamedFrom r old <$> f rendered +data NamespaceDiffResult + = NamespaceDiffResult'Ok + ( NamespaceAndLibdepsDiff + (TermTag, ShortHash) + (TypeTag, ShortHash) + TermDefinition + TypeDefinition + TermDefinitionDiff + TypeDefinitionDiff + BranchHash + ) + | NamespaceDiffResult'Err NamespaceDiffError + +instance ToJSON NamespaceDiffResult where + toJSON = \case + NamespaceDiffResult'Ok diff -> + Aeson.object + [ "defns" .= namespaceTreeDiffJSON diff.defns, + "libdeps" .= libdepsDiffJSON diff.libdeps, + "tag" .= ("ok" :: Text) + ] + NamespaceDiffResult'Err err -> + Aeson.object + [ "error" .= errValue, + "tag" .= ("error" :: Text) + ] + where + errValue = + case err of + ImpossibleError _ -> + Aeson.object + [ "errorKind" .= ("impossibleError" :: Text) + ] + IncoherentDecl reason -> + let f :: Text -> IncoherentDeclReason -> Aeson.Value + f which reason = + Aeson.object + ( "oldOrNewBranch" .= which + : case reason of + IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> + [ "errorKind" .= ("constructorAlias" :: Text), + "typeName" .= typeName, + "constructorName1" .= constructorName1, + "constructorName2" .= constructorName2 + ] + IncoherentDeclReason'MissingConstructorName typeName -> + [ "errorKind" .= ("missingConstructorName" :: Text), + "typeName" .= typeName + ] + IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> + [ "errorKind" .= ("constructorAlias" :: Text), + "constructorName1" .= constructorName1, + "constructorName2" .= constructorName2 + ] + IncoherentDeclReason'StrayConstructor _ constructorName -> + [ "errorKind" .= ("strayConstructor" :: Text), + "constructorName" .= constructorName + ] + ) + in case reason of + EitherWay.Alice reason -> f "old" reason + EitherWay.Bob reason -> f "new" reason + LibFoundAtUnexpectedPath _ -> + Aeson.object + [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) + ] + MissingEntityError _ -> + Aeson.object + [ "errorKind" .= ("missingEntityError" :: Text) + ] + where + text :: Text -> Text + text t = t + hqNameJSON :: Name -> NameSegment -> ShortHash -> Aeson.Value -> Aeson.Value + hqNameJSON fqn name sh rendered = Aeson.object ["hash" .= sh, "shortName" .= name, "fullName" .= fqn, "rendered" .= rendered] + -- The preferred frontend format is a bit clunky to calculate here: + diffDataJSON :: (ToJSON tag) => NameSegment -> DefinitionDiff (tag, ShortHash) Aeson.Value Aeson.Value -> (tag, Aeson.Value) + diffDataJSON shortName (DefinitionDiff {fqn, kind}) = case kind of + Added (defnTag, r) rendered -> (defnTag, Aeson.object ["tag" .= text "Added", "contents" .= hqNameJSON fqn shortName r rendered]) + NewAlias (defnTag, r) existingNames rendered -> + let contents = Aeson.object ["hash" .= r, "aliasShortName" .= shortName, "aliasFullName" .= fqn, "otherNames" .= toList existingNames, "rendered" .= rendered] + in (defnTag, Aeson.object ["tag" .= text "Aliased", "contents" .= contents]) + Removed (defnTag, r) rendered -> (defnTag, Aeson.object ["tag" .= text "Removed", "contents" .= hqNameJSON fqn shortName r rendered]) + Updated (oldTag, oldRef) (newTag, newRef) diffVal -> + let contents = Aeson.object ["oldHash" .= oldRef, "newHash" .= newRef, "shortName" .= shortName, "fullName" .= fqn, "oldTag" .= oldTag, "newTag" .= newTag, "diff" .= diffVal] + in (newTag, Aeson.object ["tag" .= text "Updated", "contents" .= contents]) + Propagated (oldTag, oldRef) (newTag, newRef) diffVal -> + let contents = Aeson.object ["oldHash" .= oldRef, "newHash" .= newRef, "shortName" .= shortName, "fullName" .= fqn, "oldTag" .= oldTag, "newTag" .= newTag, "diff" .= diffVal] + in (newTag, Aeson.object ["tag" .= text "Propagated", "contents" .= contents]) + RenamedTo (defnTag, r) newNames rendered -> + let contents = Aeson.object ["oldShortName" .= shortName, "oldFullName" .= fqn, "newNames" .= newNames, "hash" .= r, "rendered" .= rendered] + in (defnTag, Aeson.object ["tag" .= text "RenamedTo", "contents" .= contents]) + RenamedFrom (defnTag, r) oldNames rendered -> + let contents = Aeson.object ["oldNames" .= oldNames, "newShortName" .= shortName, "newFullName" .= fqn, "hash" .= r, "rendered" .= rendered] + in (defnTag, Aeson.object ["tag" .= text "RenamedFrom", "contents" .= contents]) + displayObjectDiffToJSON :: DisplayObjectDiff -> Aeson.Value + displayObjectDiffToJSON = \case + DisplayObjectDiff dispDiff -> + Aeson.object ["diff" .= dispDiff, "diffKind" .= ("diff" :: Text)] + MismatchedDisplayObjects {} -> + Aeson.object ["diffKind" .= ("mismatched" :: Text)] + + termDefinitionDiffToJSON :: TermDefinitionDiff -> Aeson.Value + termDefinitionDiffToJSON (TermDefinitionDiff {left, right, diff}) = Aeson.object ["left" .= left, "right" .= right, "diff" .= displayObjectDiffToJSON diff] + + typeDefinitionDiffToJSON :: TypeDefinitionDiff -> Aeson.Value + typeDefinitionDiffToJSON (TypeDefinitionDiff {left, right, diff}) = Aeson.object ["left" .= left, "right" .= right, "diff" .= displayObjectDiffToJSON diff] + + namespaceTreeDiffJSON :: + NamespaceTreeDiff + (TermTag, ShortHash) + (TypeTag, ShortHash) + TermDefinition + TypeDefinition + TermDefinitionDiff + TypeDefinitionDiff -> + Aeson.Value + namespaceTreeDiffJSON (diffs Cofree.:< children) = + let changesJSON = + diffs + & Map.toList + & foldMap + ( \(name, DiffAtPath {termDiffsAtPath, typeDiffsAtPath}) -> + ( Foldable.toList termDiffsAtPath + <&> over definitionDiffDiffs_ termDefinitionDiffToJSON + <&> over definitionDiffRendered_ toJSON + & fmap (diffDataJSON name) + & fmap (\(tag, dJSON) -> Aeson.object ["tag" .= tag, "contents" .= dJSON]) + ) + <> ( Foldable.toList typeDiffsAtPath + <&> over definitionDiffDiffs_ typeDefinitionDiffToJSON + <&> over definitionDiffRendered_ toJSON + & fmap (diffDataJSON name) + & fmap (\(tag, dJSON) -> Aeson.object ["tag" .= tag, "contents" .= dJSON]) + ) + ) + & toJSON @[Aeson.Value] + childrenJSON = + children + & Map.toList + & fmap + ( \(path, childNode) -> + Aeson.object ["path" .= path, "contents" .= namespaceTreeDiffJSON childNode] + ) + in Aeson.object + [ "changes" .= changesJSON, + "children" .= childrenJSON + ] + + libdepsDiffJSON :: Map NameSegment (DiffOp BranchHash) -> Aeson.Value + libdepsDiffJSON = + Map.toList + >>> map + ( \(name, op) -> + case op of + Merge.DiffOp'Add hash -> + Aeson.object + [ "hash" .= hash, + "name" .= name, + "tag" .= ("Added" :: Text) + ] + Merge.DiffOp'Delete hash -> + Aeson.object + [ "hash" .= hash, + "name" .= name, + "tag" .= ("Removed" :: Text) + ] + Merge.DiffOp'Update Merge.Updated {old, new} -> + Aeson.object + [ "name" .= name, + "newHash" .= new, + "oldHash" .= old, + "tag" .= ("Updated" :: Text) + ] + ) + >>> toJSON @[Aeson.Value] + type NamespaceAndLibdepsDiff referent reference renderedTerm renderedType termDiff typeDiff libdep = GNamespaceAndLibdepsDiff Path referent reference renderedTerm renderedType termDiff typeDiff libdep diff --git a/src/Share/Web/Share/Contributions/Impl.hs b/src/Share/Web/Share/Contributions/Impl.hs index 3d52e352..70078746 100644 --- a/src/Share/Web/Share/Contributions/Impl.hs +++ b/src/Share/Web/Share/Contributions/Impl.hs @@ -303,7 +303,7 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr oldRefHash = Just $ PrefixedHash oldBranchCausalHash, diff = case maybeNamespaceDiff of - Just diff -> ShareNamespaceDiffStatus'Ok (PreEncoded (ByteString.Lazy.fromStrict (Text.encodeUtf8 diff))) + Just diff -> ShareNamespaceDiffStatus'Done (PreEncoded (ByteString.Lazy.fromStrict (Text.encodeUtf8 diff))) Nothing -> ShareNamespaceDiffStatus'StillComputing } let shouldCache = isJust maybeNamespaceDiff diff --git a/src/Share/Web/Share/Diffs/Impl.hs b/src/Share/Web/Share/Diffs/Impl.hs index 3982ab6a..3f961631 100644 --- a/src/Share/Web/Share/Diffs/Impl.hs +++ b/src/Share/Web/Share/Diffs/Impl.hs @@ -5,26 +5,13 @@ module Share.Web.Share.Diffs.Impl ) where -import Control.Comonad.Cofree qualified as Cofree import Control.Lens hiding ((.=)) import Control.Monad.Except -import Data.Aeson (ToJSON (..), Value, (.=)) import Data.Aeson qualified as Aeson -import Data.Aeson.Types (object) -import Data.Foldable qualified as Foldable -import Data.Map qualified as Map import Data.Text.Lazy qualified as TL import Data.Text.Lazy.Encoding qualified as TL import Share.Codebase qualified as Codebase -import Share.NamespaceDiffs - ( DefinitionDiff (..), - DefinitionDiffKind (..), - DiffAtPath (..), - GNamespaceTreeDiff, - NamespaceAndLibdepsDiff, - NamespaceDiffError (..), - NamespaceTreeDiff, - ) +import Share.NamespaceDiffs (DefinitionDiffKind (..), GNamespaceTreeDiff, NamespaceDiffError (..)) import Share.NamespaceDiffs qualified as NamespaceDiffs import Share.Postgres qualified as PG import Share.Postgres.Causal.Queries qualified as CausalQ @@ -42,8 +29,7 @@ import Share.Web.Errors import U.Codebase.Reference qualified as V2Reference import Unison.Codebase.SqliteCodebase.Conversions (referent1to2) import Unison.ConstructorReference (ConstructorReference) -import Unison.Merge (DiffOp (..), TwoOrThreeWay (..), TwoWay (..)) -import Unison.Merge qualified as Merge +import Unison.Merge (TwoOrThreeWay (..), TwoWay (..)) import Unison.Name (Name) import Unison.NameSegment (NameSegment) import Unison.PrettyPrintEnvDecl qualified as PPED @@ -58,24 +44,40 @@ import Unison.Util.Pretty (Width) -- | Diff two causals and store the diff in the database. computeAndStoreCausalDiff :: + AuthZReceipt -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> + (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> + Maybe CausalId -> + PG.Transaction e (PreEncoded NamespaceDiffs.NamespaceDiffResult) +computeAndStoreCausalDiff authZReceipt old@(oldCodebase, _, oldCausalId) new@(newCodebase, _, newCausalId) lca = do + result <- + PG.catchTransaction (tryComputeCausalDiff authZReceipt old new lca) <&> \case + Right diff -> NamespaceDiffs.NamespaceDiffResult'Ok diff + Left err -> NamespaceDiffs.NamespaceDiffResult'Err err + let encoded = Aeson.encode result + ContributionQ.savePrecomputedNamespaceDiff + (oldCodebase, oldCausalId) + (newCodebase, newCausalId) + (TL.toStrict $ TL.decodeUtf8 encoded) + pure (PreEncoded encoded) + +tryComputeCausalDiff :: AuthZReceipt -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> (Codebase.CodebaseEnv, Codebase.CodebaseRuntime IO, CausalId) -> Maybe CausalId -> PG.Transaction NamespaceDiffError - ( PreEncoded - ( NamespaceDiffs.NamespaceAndLibdepsDiff - (TermTag, ShortHash) - (TypeTag, ShortHash) - TermDefinition - TypeDefinition - TermDefinitionDiff - TypeDefinitionDiff - BranchHash - ) + ( NamespaceDiffs.NamespaceAndLibdepsDiff + (TermTag, ShortHash) + (TypeTag, ShortHash) + TermDefinition + TypeDefinition + TermDefinitionDiff + TypeDefinitionDiff + BranchHash ) -computeAndStoreCausalDiff !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do +tryComputeCausalDiff !authZReceipt (oldCodebase, oldRuntime, oldCausalId) (newCodebase, newRuntime, newCausalId) maybeLcaCausalId = do -- Ensure name lookups for the things we're diffing. let getBranch :: CausalId -> PG.Transaction NamespaceDiffError (BranchHashId, NameLookupReceipt) getBranch causalId = do @@ -125,12 +127,7 @@ computeAndStoreCausalDiff !authZReceipt (oldCodebase, oldRuntime, oldCausalId) ( authZReceipt (oldCodebase, oldRuntime, fromMaybe oldBranchHashId maybeLcaBranchHashId) (newCodebase, newRuntime, newBranchHashId) - let encoded = Aeson.encode (RenderedNamespaceAndLibdepsDiff diff4) - ContributionQ.savePrecomputedNamespaceDiff - (oldCodebase, oldCausalId) - (newCodebase, newCausalId) - (TL.toStrict $ TL.decodeUtf8 encoded) - pure (PreEncoded encoded) + pure diff4 computeUpdatedDefinitionDiffs :: forall a b. @@ -248,120 +245,3 @@ getTypeDefinition (codebase, rt, bhId, name) = do where renderWidth :: Width renderWidth = 80 - -newtype RenderedNamespaceAndLibdepsDiff - = RenderedNamespaceAndLibdepsDiff - (NamespaceAndLibdepsDiff (TermTag, ShortHash) (TypeTag, ShortHash) TermDefinition TypeDefinition TermDefinitionDiff TypeDefinitionDiff BranchHash) - -instance ToJSON RenderedNamespaceAndLibdepsDiff where - toJSON (RenderedNamespaceAndLibdepsDiff diff) = - object - [ "defns" .= namespaceTreeDiffJSON diff.defns, - "libdeps" .= libdepsDiffJSON diff.libdeps - ] - where - text :: Text -> Text - text t = t - hqNameJSON :: Name -> NameSegment -> ShortHash -> Value -> Value - hqNameJSON fqn name sh rendered = object ["hash" .= sh, "shortName" .= name, "fullName" .= fqn, "rendered" .= rendered] - -- The preferred frontend format is a bit clunky to calculate here: - diffDataJSON :: (ToJSON tag) => NameSegment -> DefinitionDiff (tag, ShortHash) Value Value -> (tag, Value) - diffDataJSON shortName (DefinitionDiff {fqn, kind}) = case kind of - Added (defnTag, r) rendered -> (defnTag, object ["tag" .= text "Added", "contents" .= hqNameJSON fqn shortName r rendered]) - NewAlias (defnTag, r) existingNames rendered -> - let contents = object ["hash" .= r, "aliasShortName" .= shortName, "aliasFullName" .= fqn, "otherNames" .= toList existingNames, "rendered" .= rendered] - in (defnTag, object ["tag" .= text "Aliased", "contents" .= contents]) - Removed (defnTag, r) rendered -> (defnTag, object ["tag" .= text "Removed", "contents" .= hqNameJSON fqn shortName r rendered]) - Updated (oldTag, oldRef) (newTag, newRef) diffVal -> - let contents = object ["oldHash" .= oldRef, "newHash" .= newRef, "shortName" .= shortName, "fullName" .= fqn, "oldTag" .= oldTag, "newTag" .= newTag, "diff" .= diffVal] - in (newTag, object ["tag" .= text "Updated", "contents" .= contents]) - Propagated (oldTag, oldRef) (newTag, newRef) diffVal -> - let contents = object ["oldHash" .= oldRef, "newHash" .= newRef, "shortName" .= shortName, "fullName" .= fqn, "oldTag" .= oldTag, "newTag" .= newTag, "diff" .= diffVal] - in (newTag, object ["tag" .= text "Propagated", "contents" .= contents]) - RenamedTo (defnTag, r) newNames rendered -> - let contents = object ["oldShortName" .= shortName, "oldFullName" .= fqn, "newNames" .= newNames, "hash" .= r, "rendered" .= rendered] - in (defnTag, object ["tag" .= text "RenamedTo", "contents" .= contents]) - RenamedFrom (defnTag, r) oldNames rendered -> - let contents = object ["oldNames" .= oldNames, "newShortName" .= shortName, "newFullName" .= fqn, "hash" .= r, "rendered" .= rendered] - in (defnTag, object ["tag" .= text "RenamedFrom", "contents" .= contents]) - displayObjectDiffToJSON :: DisplayObjectDiff -> Value - displayObjectDiffToJSON = \case - DisplayObjectDiff dispDiff -> - object ["diff" .= dispDiff, "diffKind" .= ("diff" :: Text)] - MismatchedDisplayObjects {} -> - object ["diffKind" .= ("mismatched" :: Text)] - - termDefinitionDiffToJSON :: TermDefinitionDiff -> Value - termDefinitionDiffToJSON (TermDefinitionDiff {left, right, diff}) = object ["left" .= left, "right" .= right, "diff" .= displayObjectDiffToJSON diff] - - typeDefinitionDiffToJSON :: TypeDefinitionDiff -> Value - typeDefinitionDiffToJSON (TypeDefinitionDiff {left, right, diff}) = object ["left" .= left, "right" .= right, "diff" .= displayObjectDiffToJSON diff] - - namespaceTreeDiffJSON :: - NamespaceTreeDiff - (TermTag, ShortHash) - (TypeTag, ShortHash) - TermDefinition - TypeDefinition - TermDefinitionDiff - TypeDefinitionDiff -> - Value - namespaceTreeDiffJSON (diffs Cofree.:< children) = - let changesJSON = - diffs - & Map.toList - & foldMap - ( \(name, DiffAtPath {termDiffsAtPath, typeDiffsAtPath}) -> - ( Foldable.toList termDiffsAtPath - <&> over NamespaceDiffs.definitionDiffDiffs_ termDefinitionDiffToJSON - <&> over NamespaceDiffs.definitionDiffRendered_ toJSON - & fmap (diffDataJSON name) - & fmap (\(tag, dJSON) -> object ["tag" .= tag, "contents" .= dJSON]) - ) - <> ( Foldable.toList typeDiffsAtPath - <&> over NamespaceDiffs.definitionDiffDiffs_ typeDefinitionDiffToJSON - <&> over NamespaceDiffs.definitionDiffRendered_ toJSON - & fmap (diffDataJSON name) - & fmap (\(tag, dJSON) -> object ["tag" .= tag, "contents" .= dJSON]) - ) - ) - & toJSON @[Value] - childrenJSON = - children - & Map.toList - & fmap - ( \(path, childNode) -> - object ["path" .= path, "contents" .= namespaceTreeDiffJSON childNode] - ) - in object - [ "changes" .= changesJSON, - "children" .= childrenJSON - ] - - libdepsDiffJSON :: Map NameSegment (DiffOp BranchHash) -> Value - libdepsDiffJSON = - Map.toList - >>> map - ( \(name, op) -> - case op of - DiffOp'Add hash -> - object - [ "hash" .= hash, - "name" .= name, - "tag" .= ("Added" :: Text) - ] - DiffOp'Delete hash -> - object - [ "hash" .= hash, - "name" .= name, - "tag" .= ("Removed" :: Text) - ] - DiffOp'Update Merge.Updated {old, new} -> - object - [ "name" .= name, - "newHash" .= new, - "oldHash" .= old, - "tag" .= ("Updated" :: Text) - ] - ) - >>> toJSON @[Value] diff --git a/src/Share/Web/Share/Diffs/Types.hs b/src/Share/Web/Share/Diffs/Types.hs index c3ddf5e4..47c36507 100644 --- a/src/Share/Web/Share/Diffs/Types.hs +++ b/src/Share/Web/Share/Diffs/Types.hs @@ -4,83 +4,28 @@ module Share.Web.Share.Diffs.Types where import Data.Aeson import Share.IDs -import Share.NamespaceDiffs (NamespaceAndLibdepsDiff, NamespaceDiffError) -import Share.NamespaceDiffs qualified as NamespaceDiffs +import Share.NamespaceDiffs (NamespaceAndLibdepsDiff, NamespaceDiffResult) import Share.Postgres.IDs (BranchHash, CausalHash) import Share.Prelude import Share.Utils.Aeson (PreEncoded) -import Unison.Merge (IncoherentDeclReason (..)) -import Unison.Merge.EitherWay qualified as EitherWay -import Unison.Server.Types (DisplayObjectDiff (..), TermDefinition, TermDefinitionDiff (..), TermTag, TypeDefinition, TypeDefinitionDiff (..), TypeTag) +import Unison.Server.Types + ( DisplayObjectDiff (..), + TermDefinition, + TermDefinitionDiff (..), + TermTag, + TypeDefinition, + TypeDefinitionDiff (..), + TypeTag, + ) import Unison.ShortHash (ShortHash) type ShareNamespaceDiff = NamespaceAndLibdepsDiff (TermTag, ShortHash) (TypeTag, ShortHash) TermDefinition TypeDefinition TermDefinitionDiff TypeDefinitionDiff BranchHash data ShareNamespaceDiffStatus - = ShareNamespaceDiffStatus'Ok (PreEncoded ShareNamespaceDiff) - | ShareNamespaceDiffStatus'Error NamespaceDiffError + = ShareNamespaceDiffStatus'Done (PreEncoded NamespaceDiffResult) | ShareNamespaceDiffStatus'StillComputing --- instance ToJSON ShareNamespaceDiffStatus where --- toJSON = \case --- ShareNamespaceDiffStatus'Ok diff -> --- object --- [ "diff" .= diff, --- "diffKind" .= ("ok" :: Text) --- ] --- ShareNamespaceDiffStatus'Error err -> --- object --- [ "diffKind" .= ("error" :: Text), --- "error" --- .= case err of --- NamespaceDiffs.ImpossibleError _ -> --- object --- [ "errorKind" .= ("impossibleError" :: Text) --- ] --- NamespaceDiffs.IncoherentDecl reason -> --- let f :: Text -> IncoherentDeclReason -> Value --- f which reason = --- object --- ( "oldOrNewBranch" .= which --- : case reason of --- IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> --- [ "errorKind" .= ("constructorAlias" :: Text), --- "typeName" .= typeName, --- "constructorName1" .= constructorName1, --- "constructorName2" .= constructorName2 --- ] --- IncoherentDeclReason'MissingConstructorName typeName -> --- [ "errorKind" .= ("missingConstructorName" :: Text), --- "typeName" .= typeName --- ] --- IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> --- [ "errorKind" .= ("constructorAlias" :: Text), --- "constructorName1" .= constructorName1, --- "constructorName2" .= constructorName2 --- ] --- IncoherentDeclReason'StrayConstructor _ constructorName -> --- [ "errorKind" .= ("strayConstructor" :: Text), --- "constructorName" .= constructorName --- ] --- ) --- in case reason of --- EitherWay.Alice reason -> f "old" reason --- EitherWay.Bob reason -> f "new" reason --- NamespaceDiffs.LibFoundAtUnexpectedPath _ -> --- object --- [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) --- ] --- NamespaceDiffs.MissingEntityError _ -> --- object --- [ "errorKind" .= ("missingEntityError" :: Text) --- ] --- ] --- ShareNamespaceDiffStatus'StillComputing -> --- object --- [ "diffKind" .= ("computing" :: Text) --- ] - data ShareNamespaceDiffResponse = ShareNamespaceDiffResponse { project :: ProjectShortHand, oldRef :: BranchOrReleaseShortHand, @@ -93,74 +38,24 @@ data ShareNamespaceDiffResponse = ShareNamespaceDiffResponse instance ToJSON ShareNamespaceDiffResponse where toJSON (ShareNamespaceDiffResponse {diff, project, oldRef, newRef, oldRefHash, newRefHash}) = object $ - (maybe [] (\v -> ["diff" .= v]) diffProperty) - ++ [ "diffKind" .= diffKindProperty, - "project" .= toJSON project, + diffPairs ++ + [ "project" .= toJSON project, "oldRef" .= oldRef, "oldRefHash" .= oldRefHash, "newRef" .= newRef, "newRefHash" .= newRefHash ] where - diffKindProperty :: Text - diffKindProperty = - case diff of - ShareNamespaceDiffStatus'Ok _ -> "ok" - ShareNamespaceDiffStatus'Error _ -> "error" - ShareNamespaceDiffStatus'StillComputing -> "computing" - - diffProperty :: Maybe Value - diffProperty = + diffPairs :: [(Key, Value)] + diffPairs = case diff of - ShareNamespaceDiffStatus'Ok diff -> Just (toJSON diff) - ShareNamespaceDiffStatus'Error err -> - Just $ - object - [ "error" - .= case err of - NamespaceDiffs.ImpossibleError _ -> - object - [ "errorKind" .= ("impossibleError" :: Text) - ] - NamespaceDiffs.IncoherentDecl reason -> - let f :: Text -> IncoherentDeclReason -> Value - f which reason = - object - ( "oldOrNewBranch" .= which - : case reason of - IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> - [ "errorKind" .= ("constructorAlias" :: Text), - "typeName" .= typeName, - "constructorName1" .= constructorName1, - "constructorName2" .= constructorName2 - ] - IncoherentDeclReason'MissingConstructorName typeName -> - [ "errorKind" .= ("missingConstructorName" :: Text), - "typeName" .= typeName - ] - IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> - [ "errorKind" .= ("constructorAlias" :: Text), - "constructorName1" .= constructorName1, - "constructorName2" .= constructorName2 - ] - IncoherentDeclReason'StrayConstructor _ constructorName -> - [ "errorKind" .= ("strayConstructor" :: Text), - "constructorName" .= constructorName - ] - ) - in case reason of - EitherWay.Alice reason -> f "old" reason - EitherWay.Bob reason -> f "new" reason - NamespaceDiffs.LibFoundAtUnexpectedPath _ -> - object - [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) - ] - NamespaceDiffs.MissingEntityError _ -> - object - [ "errorKind" .= ("missingEntityError" :: Text) - ] - ] - ShareNamespaceDiffStatus'StillComputing -> Nothing + ShareNamespaceDiffStatus'Done diff -> + [ "diff" .= toJSON diff + , "tag" .= ("done" :: Text) + ] + ShareNamespaceDiffStatus'StillComputing -> + [ "tag" .= ("computing" :: Text) + ] data ShareTermDiffResponse = ShareTermDiffResponse { project :: ProjectShortHand, diff --git a/src/Share/Web/Share/Projects/Impl.hs b/src/Share/Web/Share/Projects/Impl.hs index d638f537..c8e11b2e 100644 --- a/src/Share/Web/Share/Projects/Impl.hs +++ b/src/Share/Web/Share/Projects/Impl.hs @@ -177,8 +177,8 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project makeRuntime codebase = do runtime <- Codebase.codebaseRuntime' unisonRuntime codebase pure (badUnliftCodebaseRuntime runtime) - diffOrError <- - PG.tryRunTransaction do + diff <- + PG.runTransaction do ContributionsQ.getPrecomputedNamespaceDiff (oldCodebase, oldCausalId) (newCodebase, newCausalId) >>= \case Just diff -> pure (PreEncoded (ByteString.Lazy.fromStrict (Text.encodeUtf8 diff))) Nothing -> do @@ -196,10 +196,7 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project oldRefHash = Just $ PrefixedHash oldCausalHash, newRef = newShortHand, newRefHash = Just $ PrefixedHash newCausalHash, - diff = - case diffOrError of - Right diff -> ShareNamespaceDiffStatus'Ok diff - Left err -> ShareNamespaceDiffStatus'Error err + diff = ShareNamespaceDiffStatus'Done diff } where projectShortHand = IDs.ProjectShortHand {userHandle, projectSlug} diff --git a/transcripts/share-apis/contribution-diffs/contribution-diff.json b/transcripts/share-apis/contribution-diffs/contribution-diff.json index 9b9f0f23..fea19a85 100644 --- a/transcripts/share-apis/contribution-diffs/contribution-diff.json +++ b/transcripts/share-apis/contribution-diffs/contribution-diff.json @@ -2689,14 +2689,15 @@ } ] }, - "libdeps": [] + "libdeps": [], + "tag": "ok" }, - "diffKind": "ok", "newRef": "diff-end", "newRefHash": "#f2bjgi4tm53bf6dcfcukt5a6as3ktlrbiacnqq81nco8i4g7dg6pt14vmc1b7ulsb7rt683qjt2rvg9u92uo5mk1gaqgo8cl30umep8", "oldRef": "diff-start", "oldRefHash": "#f8nji6tc2vaorc7gl8kjdmj8ucrht674blmb586iptgsa8v1pm8ovjplc4an2voirvlip91ick9g5mjkncsmr8sadaqqf8810eskbig", - "project": "@transcripts/contribution-diff" + "project": "@transcripts/contribution-diff", + "tag": "done" }, "status": [ { diff --git a/transcripts/share-apis/contribution-diffs/namespace-diff.json b/transcripts/share-apis/contribution-diffs/namespace-diff.json index 9b9f0f23..fea19a85 100644 --- a/transcripts/share-apis/contribution-diffs/namespace-diff.json +++ b/transcripts/share-apis/contribution-diffs/namespace-diff.json @@ -2689,14 +2689,15 @@ } ] }, - "libdeps": [] + "libdeps": [], + "tag": "ok" }, - "diffKind": "ok", "newRef": "diff-end", "newRefHash": "#f2bjgi4tm53bf6dcfcukt5a6as3ktlrbiacnqq81nco8i4g7dg6pt14vmc1b7ulsb7rt683qjt2rvg9u92uo5mk1gaqgo8cl30umep8", "oldRef": "diff-start", "oldRefHash": "#f8nji6tc2vaorc7gl8kjdmj8ucrht674blmb586iptgsa8v1pm8ovjplc4an2voirvlip91ick9g5mjkncsmr8sadaqqf8810eskbig", - "project": "@transcripts/contribution-diff" + "project": "@transcripts/contribution-diff", + "tag": "done" }, "status": [ { diff --git a/transcripts/share-apis/contributions/merged-contribution-diff.json b/transcripts/share-apis/contributions/merged-contribution-diff.json index 2f176c32..39b241d9 100644 --- a/transcripts/share-apis/contributions/merged-contribution-diff.json +++ b/transcripts/share-apis/contributions/merged-contribution-diff.json @@ -248,14 +248,15 @@ ], "children": [] }, - "libdeps": [] + "libdeps": [], + "tag": "ok" }, - "diffKind": "ok", "newRef": "feature-one", "newRefHash": "#7shvkj0gn9mfne1pemp3oudmo23vio4d8ualvbah6avr7m5471rssu9cd4o6i4pn91bgc62vgnm0oper0itgtmopqmff7c0b40ui1s0", "oldRef": "main", "oldRefHash": "#7shvkj0gn9mfne1pemp3oudmo23vio4d8ualvbah6avr7m5471rssu9cd4o6i4pn91bgc62vgnm0oper0itgtmopqmff7c0b40ui1s0", - "project": "@transcripts/bca-updates" + "project": "@transcripts/bca-updates", + "tag": "done" }, "status": [ { diff --git a/transcripts/share-apis/contributions/transitive-contribution-diff.json b/transcripts/share-apis/contributions/transitive-contribution-diff.json index 9b42a415..34bedd9e 100644 --- a/transcripts/share-apis/contributions/transitive-contribution-diff.json +++ b/transcripts/share-apis/contributions/transitive-contribution-diff.json @@ -248,14 +248,15 @@ ], "children": [] }, - "libdeps": [] + "libdeps": [], + "tag": "ok" }, - "diffKind": "ok", "newRef": "feature-two", "newRefHash": "#ktjspqi8s5ngg129a6lt7i9kd488isfoq8hqmsv54f327de28dq9u0n1dp1vlbgs8jdc6bqss3h46ep9241405ml19nr0gekel56pig", "oldRef": "main", "oldRefHash": "#7shvkj0gn9mfne1pemp3oudmo23vio4d8ualvbah6avr7m5471rssu9cd4o6i4pn91bgc62vgnm0oper0itgtmopqmff7c0b40ui1s0", - "project": "@transcripts/bca-updates" + "project": "@transcripts/bca-updates", + "tag": "done" }, "status": [ { From 76fe8d8623257420fcc61ec2d38529c5f77ec24c Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Thu, 1 May 2025 14:02:55 -0400 Subject: [PATCH 13/16] change "errorKind" to "tag" in error json --- src/Share/NamespaceDiffs.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Share/NamespaceDiffs.hs b/src/Share/NamespaceDiffs.hs index 9e065056..6fc7af50 100644 --- a/src/Share/NamespaceDiffs.hs +++ b/src/Share/NamespaceDiffs.hs @@ -259,7 +259,7 @@ instance ToJSON NamespaceDiffResult where case err of ImpossibleError _ -> Aeson.object - [ "errorKind" .= ("impossibleError" :: Text) + [ "tag" .= ("impossibleError" :: Text) ] IncoherentDecl reason -> let f :: Text -> IncoherentDeclReason -> Aeson.Value @@ -268,22 +268,22 @@ instance ToJSON NamespaceDiffResult where ( "oldOrNewBranch" .= which : case reason of IncoherentDeclReason'ConstructorAlias typeName constructorName1 constructorName2 -> - [ "errorKind" .= ("constructorAlias" :: Text), + [ "tag" .= ("constructorAlias" :: Text), "typeName" .= typeName, "constructorName1" .= constructorName1, "constructorName2" .= constructorName2 ] IncoherentDeclReason'MissingConstructorName typeName -> - [ "errorKind" .= ("missingConstructorName" :: Text), + [ "tag" .= ("missingConstructorName" :: Text), "typeName" .= typeName ] IncoherentDeclReason'NestedDeclAlias constructorName1 constructorName2 -> - [ "errorKind" .= ("constructorAlias" :: Text), + [ "tag" .= ("constructorAlias" :: Text), "constructorName1" .= constructorName1, "constructorName2" .= constructorName2 ] IncoherentDeclReason'StrayConstructor _ constructorName -> - [ "errorKind" .= ("strayConstructor" :: Text), + [ "tag" .= ("strayConstructor" :: Text), "constructorName" .= constructorName ] ) @@ -292,11 +292,11 @@ instance ToJSON NamespaceDiffResult where EitherWay.Bob reason -> f "new" reason LibFoundAtUnexpectedPath _ -> Aeson.object - [ "errorKind" .= ("libFoundAtUnexpectedPath" :: Text) + [ "tag" .= ("libFoundAtUnexpectedPath" :: Text) ] MissingEntityError _ -> Aeson.object - [ "errorKind" .= ("missingEntityError" :: Text) + [ "tag" .= ("missingEntityError" :: Text) ] where text :: Text -> Text From 4c256d138e96ac36293860fca46c9f853da968e7 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Tue, 6 May 2025 09:57:00 -0400 Subject: [PATCH 14/16] don't ping background worker in get contribution diff endpoint --- sql/2025-04-30-contribution-diff-queue.sql | 13 ------------- sql/2025-04-30-drop-namespace-diffs.sql | 3 +++ src/Share/BackgroundJobs/Diffs/Queries.hs | 12 +----------- src/Share/Web/Share/Contributions/Impl.hs | 4 ---- 4 files changed, 4 insertions(+), 28 deletions(-) delete mode 100644 sql/2025-04-30-contribution-diff-queue.sql create mode 100644 sql/2025-04-30-drop-namespace-diffs.sql diff --git a/sql/2025-04-30-contribution-diff-queue.sql b/sql/2025-04-30-contribution-diff-queue.sql deleted file mode 100644 index c09ac929..00000000 --- a/sql/2025-04-30-contribution-diff-queue.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Drop and re-create the contribution_diff_queue table without a primary key constraint on contribution_id. --- This allows us to insert redundant rows while a diff is being computed, rather than blocking due to row lock. - -DROP TABLE contribution_diff_queue; - -CREATE TABLE contribution_diff_queue ( - contribution_id UUID REFERENCES contributions(id) ON DELETE CASCADE, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - --- Delete all previously-computed namespace diffs, because the diff payload is different now (we explicitly store --- errors). -TRUNCATE namespace_diffs; diff --git a/sql/2025-04-30-drop-namespace-diffs.sql b/sql/2025-04-30-drop-namespace-diffs.sql new file mode 100644 index 00000000..530e9f9b --- /dev/null +++ b/sql/2025-04-30-drop-namespace-diffs.sql @@ -0,0 +1,3 @@ +-- Delete all previously-computed namespace diffs, because the diff payload is different now (we explicitly store +-- errors). +TRUNCATE namespace_diffs; diff --git a/src/Share/BackgroundJobs/Diffs/Queries.hs b/src/Share/BackgroundJobs/Diffs/Queries.hs index 184e596b..3a4b6e7b 100644 --- a/src/Share/BackgroundJobs/Diffs/Queries.hs +++ b/src/Share/BackgroundJobs/Diffs/Queries.hs @@ -1,6 +1,5 @@ module Share.BackgroundJobs.Diffs.Queries - ( submitContributionToBeDiffed, - submitContributionsToBeDiffed, + ( submitContributionsToBeDiffed, claimContributionToDiff, ) where @@ -10,15 +9,6 @@ import Share.Postgres import Share.Postgres.Notifications qualified as Notif import Unison.Prelude -submitContributionToBeDiffed :: (QueryM m) => ContributionId -> m () -submitContributionToBeDiffed contributionId = do - execute_ - [sql| - INSERT INTO contribution_diff_queue (contribution_id) - VALUES (#{contributionId}) - |] - Notif.notifyChannel Notif.ContributionDiffChannel - submitContributionsToBeDiffed :: (QueryM m) => Set ContributionId -> m () submitContributionsToBeDiffed contributions = do execute_ diff --git a/src/Share/Web/Share/Contributions/Impl.hs b/src/Share/Web/Share/Contributions/Impl.hs index 70078746..84b088c2 100644 --- a/src/Share/Web/Share/Contributions/Impl.hs +++ b/src/Share/Web/Share/Contributions/Impl.hs @@ -290,10 +290,6 @@ contributionDiffEndpoint (AuthN.MaybeAuthedUserID mayCallerUserId) userHandle pr <$> CausalQ.expectCausalHashesByIdsOf id oldBranchCausalId <*> CausalQ.expectCausalHashesByIdsOf id newBranchCausalId <*> ContributionsQ.getPrecomputedNamespaceDiff (oldCodebase, oldBranchCausalId) (newCodebase, newBranchCausalId) - -- If the diff hasn't been computed by a background worker yet, signal interest in it (perhaps redundantly), in case - -- it had been picked up by a worker that then went on to crash before completing and storing the diff. - when (isNothing maybeNamespaceDiff) do - PG.runTransaction (DiffsQ.submitContributionToBeDiffed contributionId) let response = ShareNamespaceDiffResponse { project = projectShorthand, From 7ed3d7510b70c614b3c99a6467a2d13b0bf9ee28 Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Tue, 6 May 2025 10:01:22 -0400 Subject: [PATCH 15/16] check notification channels on startup --- src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs | 4 ++-- src/Share/Postgres/Notifications.hs | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 567621a3..6d1213ec 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -25,10 +25,10 @@ import Share.Web.Errors (EntityMissing (..), ErrorID (..)) import Share.Web.Share.Diffs.Impl qualified as Diffs import System.Clock qualified as Clock --- | Check every 30 seconds if we haven't heard on the notifications channel. +-- | Check every 10 minutes if we haven't heard on the notifications channel. -- Just in case we missed a notification. maxPollingIntervalSeconds :: Int -maxPollingIntervalSeconds = 30 +maxPollingIntervalSeconds = 10 * 60 worker :: Ki.Scope -> Background () worker scope = do diff --git a/src/Share/Postgres/Notifications.hs b/src/Share/Postgres/Notifications.hs index 30a2e619..f6699ff2 100644 --- a/src/Share/Postgres/Notifications.hs +++ b/src/Share/Postgres/Notifications.hs @@ -30,8 +30,10 @@ data NotificationError deriving stock (Show) deriving (Logging.Loggable) via (Logging.ShowLoggable Logging.Error NotificationError) +-- Initialize the set of channel kinds to check with every channel kind, so that on server startup, workers do any +-- outstanding work. notifs :: TVar (Set ChannelKind) -notifs = unsafePerformIO $ STM.newTVarIO mempty +notifs = unsafePerformIO $ STM.newTVarIO allChannels {-# NOINLINE notifs #-} -- | Initializes the notification worker, which listens for notifications from the database. @@ -42,7 +44,7 @@ initialize :: initialize scope = Ki.fork_ scope $ forever do result <- UnliftIO.try $ do PG.runSession $ do - for_ [minBound .. maxBound] \kind -> do + for_ allChannels \kind -> do PG.statement () $ Hasql.listen (Hasql.Identifier . Text.encodeUtf8 $ toChannelText kind) -- Wait for notifications let loop = do @@ -76,6 +78,10 @@ fromChannelText = \case "contribution_diff" -> Just ContributionDiffChannel _ -> Nothing +allChannels :: Set ChannelKind +allChannels = + Set.fromList [minBound .. maxBound] + -- | Block waiting on a channel until either we get a notification OR until the max polling time has been reached -- -- The channel notifications can help ensure we process items as they come in, but they're not From d6e926c418e4c3105d4fd238e6c901158f31ae7f Mon Sep 17 00:00:00 2001 From: Mitchell Dalvi Rosen Date: Tue, 6 May 2025 10:46:11 -0400 Subject: [PATCH 16/16] address more PR comments --- .../BackgroundJobs/Diffs/ContributionDiffs.hs | 9 +++---- src/Share/Codebase.hs | 11 +++++--- src/Share/NamespaceDiffs.hs | 6 ++--- src/Share/Postgres.hs | 27 ++++++++++++------- src/Share/Postgres/Causal/Queries.hs | 1 - src/Share/Postgres/Definitions/Queries.hs | 24 ++++++++--------- src/Share/Postgres/Hashes/Queries.hs | 26 ------------------ src/Share/Web/Share/Projects/Impl.hs | 2 +- 8 files changed, 45 insertions(+), 61 deletions(-) diff --git a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs index 6d1213ec..b3ceb87b 100644 --- a/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs +++ b/src/Share/BackgroundJobs/Diffs/ContributionDiffs.hs @@ -37,16 +37,15 @@ worker scope = do unisonRuntime <- asks Env.sandboxedRuntime let makeRuntime :: Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO) makeRuntime codebase = do - runtime <- Codebase.codebaseRuntime' unisonRuntime codebase + runtime <- Codebase.codebaseRuntimeTransaction unisonRuntime codebase pure (badUnliftCodebaseRuntime runtime) newWorker scope "diffs:contributions" $ forever do Notif.waitOnChannel Notif.ContributionDiffChannel (maxPollingIntervalSeconds * 1000000) processDiffs authZReceipt makeRuntime --- Process diffs until we run out of them. We claim a diff in a transaction, commit it, then proceed to compute the --- diff. There's therefore a chance we claim a diff and fail to compute it (due to e.g. server restart). The current --- solution to these "at most once" semantics is to simply re-enqueue a diff job if necessary; e.g. in the view diff --- endpoint handler. +-- Process diffs until we run out of them. We claim a diff in a transaction and compute the diff in the same +-- transaction, with a row lock on the contribution id (which is skipped by other workers). There's therefore no chance +-- that we claim a diff but fail to write the result of computing that diff back to the database. processDiffs :: AuthZ.AuthZReceipt -> (Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO)) -> Background () processDiffs authZReceipt makeRuntime = do let loop :: Background () diff --git a/src/Share/Codebase.hs b/src/Share/Codebase.hs index d69138f9..ac178058 100644 --- a/src/Share/Codebase.hs +++ b/src/Share/Codebase.hs @@ -17,7 +17,7 @@ module Share.Codebase CodebaseRuntime (..), codebaseEnv, codebaseRuntime, - codebaseRuntime', + codebaseRuntimeTransaction, badAskUnliftCodebaseRuntime, codebaseForProjectBranch, codebaseLocationForUserCodebase, @@ -189,7 +189,7 @@ codebaseEnv !_authZReceipt codebaseLoc = do codebaseRuntime :: (MonadReader (Env.Env x) m, MonadUnliftIO m) => CodebaseEnv -> m (CodebaseRuntime IO) codebaseRuntime codebase = do unisonRuntime <- asks Env.sandboxedRuntime - rt <- liftIO (codebaseRuntime' unisonRuntime codebase) + rt <- liftIO (codebaseRuntimeTransaction unisonRuntime codebase) unlift <- badAskUnliftCodebaseRuntime pure (unlift rt) @@ -197,8 +197,8 @@ codebaseRuntime codebase = do -- the runtime interface in ucm, so we can't use it for now. That's bad: we end up unsafely running separate -- transactions for inner calls to 'codeLookup' / 'cachedEvalResult', which can lead to deadlock due to a starved -- connection pool. -codebaseRuntime' :: Runtime Symbol -> CodebaseEnv -> IO (CodebaseRuntime (PG.Transaction e)) -codebaseRuntime' unisonRuntime CodebaseEnv {codebaseOwner} = do +codebaseRuntimeTransaction :: Runtime Symbol -> CodebaseEnv -> IO (CodebaseRuntime (PG.Transaction e)) +codebaseRuntimeTransaction unisonRuntime CodebaseEnv {codebaseOwner} = do cacheVar <- newTVarIO (CodeLookupCache mempty mempty) pure CodebaseRuntime @@ -207,6 +207,9 @@ codebaseRuntime' unisonRuntime CodebaseEnv {codebaseOwner} = do unisonRuntime } +-- Why bad: see above comment on `codebaseRuntimeTransaction`. We don't want to use a `CodebaseRuntime IO`, because it +-- will run every lookup in a separate transaction. But we can't use a `CodebaseRuntime Transaction` because we call +-- back into UCM library code that expects a `CodebaseRuntime IO`. badAskUnliftCodebaseRuntime :: (MonadReader (Env.Env x) m, MonadUnliftIO m) => m (CodebaseRuntime (PG.Transaction Void) -> CodebaseRuntime IO) diff --git a/src/Share/NamespaceDiffs.hs b/src/Share/NamespaceDiffs.hs index 6fc7af50..79827671 100644 --- a/src/Share/NamespaceDiffs.hs +++ b/src/Share/NamespaceDiffs.hs @@ -817,10 +817,10 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = let termReferenceIds = Map.mapMaybe Referent.toTermReferenceId (BiMultimap.range termReferents) termIds <- PG.pFor termReferenceIds \refId -> - (refId,) <$> DefnsQ.pipelinedExpectTermId refId + (refId,) <$> DefnsQ.expectTermId refId v2Terms <- PG.pFor termIds \(refId, termId) -> - (refId,) <$> DefnsQ.pipelinedExpectTermById codebaseUser refId termId + (refId,) <$> DefnsQ.expectTermById codebaseUser refId termId v1Terms <- for v2Terms \(refId, (term, typ)) -> (refId,) <$> Codebase.convertTerm2to1 (Reference.idToHash refId) term typ @@ -833,7 +833,7 @@ computeThreeWayNamespaceDiff codebaseEnvs2 branchHashIds3 nameLookupReceipts3 = let typeReferenceIds = Map.mapMaybe Reference.toId (BiMultimap.range typeReferences) typeIds <- PG.pFor typeReferenceIds \refId -> - (refId,) <$> DefnsQ.pipelinedExpectTypeComponentElementAndTypeId codebaseUser refId + (refId,) <$> DefnsQ.expectTypeComponentElementAndTypeId codebaseUser refId v1Decls <- PG.pFor typeIds \(refId, typeId) -> DefnsQ.loadDeclByTypeComponentElementAndTypeId typeId <&> \v2Decl -> diff --git a/src/Share/Postgres.hs b/src/Share/Postgres.hs index a472393c..8e9eefe9 100644 --- a/src/Share/Postgres.hs +++ b/src/Share/Postgres.hs @@ -1,4 +1,5 @@ {-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE ImpredicativeTypes #-} {-# LANGUAGE LiberalTypeSynonyms #-} @@ -45,7 +46,6 @@ module Share.Postgres defaultIsolationLevel, pipelined, pEitherMap, - pUnrecoverableEitherMap, pFor, pFor_, @@ -139,14 +139,6 @@ pEitherMap f (Pipeline p) = Right x -> mapLeft Err (f x) Left e -> Left e --- | Like 'pEitherMap', but for throwing unrecoverable errors. -pUnrecoverableEitherMap :: (Loggable e, Show e, ToServerError e) => (a -> Either e b) -> Pipeline e' a -> Pipeline e' b -pUnrecoverableEitherMap f (Pipeline p) = - Pipeline $ - p <&> \case - Right x -> mapLeft (Unrecoverable . someServerError) (f x) - Left e -> Left e - pFor :: (Traversable f) => f a -> (a -> Pipeline e b) -> Transaction e (f b) pFor f p = pipelined $ for f p @@ -346,6 +338,17 @@ class (Applicative m) => QueryA m where -- | Fail the transaction and whole request with an unrecoverable server error. unrecoverableError :: (HasCallStack, ToServerError e, Loggable e, Show e) => e -> m a + -- | Map an either-returning function over the result of an action; if it returns Left, throw an unrecoverable error. + -- This is a trivial combinator for any monad, hence the default signature, but it can be implemented by our + -- Pipeline applicative, too. + unrecoverableEitherMap :: (HasCallStack, Loggable e, Show e, ToServerError e) => (a -> Either e b) -> m a -> m b + default unrecoverableEitherMap :: (HasCallStack, Loggable e, Show e, ToServerError e, Monad m) => (a -> Either e b) -> m a -> m b + unrecoverableEitherMap f m = do + x <- m + case f x of + Right y -> pure y + Left e -> unrecoverableError e + class (Monad m, QueryA m) => QueryM m where -- | Allow running IO actions in a transaction. These actions may be run multiple times if -- the transaction is retried. @@ -376,6 +379,12 @@ instance QueryA (Pipeline e) where unrecoverableError e = Pipeline $ pure (Left (Unrecoverable (someServerError e))) + unrecoverableEitherMap f (Pipeline p) = + Pipeline $ + p <&> \case + Right x -> mapLeft (Unrecoverable . someServerError) (f x) + Left e -> Left e + instance (QueryM m) => QueryA (ReaderT e m) where statement q s = lift $ statement q s diff --git a/src/Share/Postgres/Causal/Queries.hs b/src/Share/Postgres/Causal/Queries.hs index 405b564f..8cac1104 100644 --- a/src/Share/Postgres/Causal/Queries.hs +++ b/src/Share/Postgres/Causal/Queries.hs @@ -20,7 +20,6 @@ module Share.Postgres.Causal.Queries expectNamespaceStatsOf, expectNamespaceHashByCausalHash, HashQ.expectNamespaceIdsByCausalIdsOf, - HashQ.pipelinedExpectNamespaceIdsByCausalIdsOf, importAccessibleCausals, importCausalIntoCodebase, hashCausal, diff --git a/src/Share/Postgres/Definitions/Queries.hs b/src/Share/Postgres/Definitions/Queries.hs index b50f8a08..ae9254ee 100644 --- a/src/Share/Postgres/Definitions/Queries.hs +++ b/src/Share/Postgres/Definitions/Queries.hs @@ -3,8 +3,8 @@ module Share.Postgres.Definitions.Queries ( loadTerm, expectTerm, - pipelinedExpectTermId, - pipelinedExpectTermById, + expectTermId, + expectTermById, saveTermComponent, saveEncodedTermComponent, loadTermComponent, @@ -20,7 +20,7 @@ module Share.Postgres.Definitions.Queries loadDecl, expectDecl, loadDeclByTypeComponentElementAndTypeId, - pipelinedExpectTypeComponentElementAndTypeId, + expectTypeComponentElementAndTypeId, loadCachedEvalResult, saveCachedEvalResult, termReferencesByPrefix, @@ -153,9 +153,9 @@ loadTermId (Reference.Id compHash (pgComponentIndex -> compIndex)) = AND term.component_index = #{compIndex} |] -pipelinedExpectTermId :: TermReferenceId -> PG.Pipeline e TermId -pipelinedExpectTermId refId = - pUnrecoverableEitherMap +expectTermId :: QueryA m => TermReferenceId -> m TermId +expectTermId refId = + unrecoverableEitherMap ( \case Nothing -> Left (expectedTermError refId) Just termId -> Right termId @@ -310,9 +310,9 @@ loadTermById codebaseUser termId = do <$> loadTermComponentElementByTermId codebaseUser termId <*> termLocalReferences termId -pipelinedExpectTermById :: UserId -> TermReferenceId -> TermId -> Pipeline e (V2.Term Symbol, V2.Type Symbol) -pipelinedExpectTermById userId refId termId = - pUnrecoverableEitherMap +expectTermById :: QueryA m => UserId -> TermReferenceId -> TermId -> m (V2.Term Symbol, V2.Type Symbol) +expectTermById userId refId termId = + unrecoverableEitherMap ( \case Nothing -> Left (expectedTermError refId) Just term -> Right term @@ -443,9 +443,9 @@ loadTypeComponentElementAndTypeId codebaseUser (Reference.Id compHash (pgCompone AND typ.component_index = #{compIndex} |] -pipelinedExpectTypeComponentElementAndTypeId :: UserId -> TermReferenceId -> PG.Pipeline e (TypeComponentElement, TypeId) -pipelinedExpectTypeComponentElementAndTypeId codebaseUser refId = - pUnrecoverableEitherMap +expectTypeComponentElementAndTypeId :: QueryA m => UserId -> TermReferenceId -> m (TypeComponentElement, TypeId) +expectTypeComponentElementAndTypeId codebaseUser refId = + unrecoverableEitherMap ( \case Nothing -> Left (expectedTypeError refId) Just decl -> Right decl diff --git a/src/Share/Postgres/Hashes/Queries.hs b/src/Share/Postgres/Hashes/Queries.hs index 0b452692..6d422a0a 100644 --- a/src/Share/Postgres/Hashes/Queries.hs +++ b/src/Share/Postgres/Hashes/Queries.hs @@ -29,7 +29,6 @@ module Share.Postgres.Hashes.Queries loadCausalIdByHash, expectCausalIdByHash, expectNamespaceIdsByCausalIdsOf, - pipelinedExpectNamespaceIdsByCausalIdsOf, expectNamespaceHashesByNamespaceHashIdsOf, isComponentHashAllowedToBeMismatched, isCausalHashAllowedToBeMismatched, @@ -305,31 +304,6 @@ expectNamespaceIdsByCausalIdsOf trav s = do then unrecoverableError . MissingExpectedEntity $ "expectNamespaceIdsByCausalIdsOf: Expected to get the same number of results as causal ids. " <> tShow causalIds else pure results --- | Mitchell says: this could/should just have replaced 'expectNamespaceIdsByCausalIdsOf', but that function has --- many callers, so having two temporarily eases the transition. -pipelinedExpectNamespaceIdsByCausalIdsOf :: Traversal s t CausalId BranchHashId -> s -> Pipeline e t -pipelinedExpectNamespaceIdsByCausalIdsOf trav s = do - s - & unsafePartsOf trav %%~ \causalIds -> - let causalIdsTable = ordered causalIds - in pUnrecoverableEitherMap - ( \results -> - if length results /= length causalIds - then Left (MissingExpectedEntity $ "expectNamespaceIdsByCausalIdsOf: Expected to get the same number of results as causal ids. " <> tShow causalIds) - else Right results - ) - ( queryListCol @BranchHashId - [sql| - WITH causal_ids(ord, causal_id) AS ( - SELECT ord, causal_id FROM ^{toTable causalIdsTable} as t(ord, causal_id) - ) - SELECT c.namespace_hash_id - FROM causal_ids cid - JOIN causals c ON cid.causal_id = c.id - ORDER BY cid.ord - |] - ) - expectNamespaceHashesByNamespaceHashIdsOf :: (HasCallStack, QueryM m) => Traversal s t BranchHashId BranchHash -> s -> m t expectNamespaceHashesByNamespaceHashIdsOf trav s = do s diff --git a/src/Share/Web/Share/Projects/Impl.hs b/src/Share/Web/Share/Projects/Impl.hs index c8e11b2e..1df6fe37 100644 --- a/src/Share/Web/Share/Projects/Impl.hs +++ b/src/Share/Web/Share/Projects/Impl.hs @@ -175,7 +175,7 @@ diffNamespacesEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle project unisonRuntime <- asks Env.sandboxedRuntime let makeRuntime :: Codebase.CodebaseEnv -> IO (Codebase.CodebaseRuntime IO) makeRuntime codebase = do - runtime <- Codebase.codebaseRuntime' unisonRuntime codebase + runtime <- Codebase.codebaseRuntimeTransaction unisonRuntime codebase pure (badUnliftCodebaseRuntime runtime) diff <- PG.runTransaction do