spec references in code

This commit is contained in:
Evgeny @ SimpleX Chat
2026-03-11 09:06:05 +00:00
parent 66d7efa61e
commit e5dbe97e1d
6 changed files with 30 additions and 6 deletions
+14 -5
View File
@@ -119,14 +119,23 @@ See [rcv-services](../rcv-services.md) for the end-to-end service subscription f
```
### Source → module doc
Comment above function in source:
Add `-- spec:` comments as part of the module documentation work — when you document something non-obvious, add the link in source at the same time. Two levels:
**Module-level** (below the module declaration): when the Overview section has value.
```haskell
-- spec: spec/modules/Simplex/Messaging/Server.md#subscribeServiceMessages
-- Delivers buffered messages for all service queues after SUBS (SI-SVC-07)
subscribeServiceMessages :: ...
module Simplex.Messaging.Util (...) where
-- spec: spec/modules/Simplex/Messaging/Util.md
```
Only add `-- spec:` comments where the module doc actually has something to say. Don't add links to "No non-obvious behavior" docs.
**Function-level** (above the function): when that function has a doc entry worth pointing to.
```haskell
-- spec: spec/modules/Simplex/Messaging/Util.md#catchOwn
-- Catches all exceptions except async cancellations (misleading name)
catchOwn :: ...
```
Only add `-- spec:` comments where the module doc actually says something the code doesn't. Don't add links to "No non-obvious behavior" docs or to entries that merely restate the source.
## Topic candidate tracking
+3
View File
@@ -1,6 +1,7 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
-- spec: spec/modules/Simplex/Messaging/Compression.md
module Simplex.Messaging.Compression
( Compressed,
maxLengthPassthrough,
@@ -42,6 +43,8 @@ compress1 bs
| B.length bs <= maxLengthPassthrough = Passthrough bs
| otherwise = Compressed . Large $ Z1.compress compressionLevel bs
-- spec: spec/modules/Simplex/Messaging/Compression.md#decompress1
-- Decompression bomb protection: refuses data without declared size or exceeding limit
decompress1 :: Int -> Compressed -> Either String ByteString
decompress1 limit = \case
Passthrough bs -> Right bs
+1
View File
@@ -7,6 +7,7 @@
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
-- spec: spec/modules/Simplex/Messaging/Encoding.md
module Simplex.Messaging.Encoding
( Encoding (..),
Tail (..),
+3 -1
View File
@@ -4,6 +4,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
-- spec: spec/modules/Simplex/Messaging/Parsers.md
module Simplex.Messaging.Parsers
( base64P,
parse,
@@ -105,7 +106,8 @@ enumJSON tagModifier =
J.allNullaryToStringTag = True
}
-- used in platform-specific encoding, includes tag for single-field encoding of sum types to allow conversion to tagged objects
-- spec: spec/modules/Simplex/Messaging/Parsers.md#sumTypeJSON
-- Platform-dependent: ObjectWithSingleField on Darwin+swiftJSON, TaggedObject elsewhere
sumTypeJSON :: (String -> String) -> J.Options
#if defined(darwin_HOST_OS) && defined(swiftJSON)
sumTypeJSON = singleFieldJSON_ $ Just SingleFieldJSONTag
+3
View File
@@ -2,6 +2,7 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- spec: spec/modules/Simplex/Messaging/Session.md
module Simplex.Messaging.Session
( SessionVar (..),
getSessVar,
@@ -32,6 +33,8 @@ getSessVar sessSeq sessKey vs sessionVarTs = maybe (Left <$> newSessionVar) (pur
TM.insert sessKey v vs
pure v
-- spec: spec/modules/Simplex/Messaging/Session.md#removeSessVar
-- Compare-and-swap: only removes if sessionVarId matches, preventing stale removal
removeSessVar :: Ord k => SessionVar a -> k -> TMap k (SessionVar a) -> STM ()
removeSessVar v sessKey vs =
TM.lookup sessKey vs >>= \case
+6
View File
@@ -3,6 +3,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- spec: spec/modules/Simplex/Messaging/Util.md
module Simplex.Messaging.Util
( AnyError (..),
(<$?>),
@@ -294,6 +295,7 @@ allFinally :: (AnyError e, MonadUnliftIO m) => ExceptT e m a -> ExceptT e m b ->
allFinally action final = tryAllErrors action >>= \r -> final >> except r
{-# INLINE allFinally #-}
-- spec: spec/modules/Simplex/Messaging/Util.md#isOwnException
isOwnException :: E.SomeException -> Bool
isOwnException e = case E.fromException e of
Just StackOverflow -> True
@@ -303,16 +305,20 @@ isOwnException e = case E.fromException e of
_ -> False
{-# INLINE isOwnException #-}
-- spec: spec/modules/Simplex/Messaging/Util.md#isAsyncCancellation
isAsyncCancellation :: E.SomeException -> Bool
isAsyncCancellation e = case E.fromException e of
Just (_ :: SomeAsyncException) -> not $ isOwnException e
Nothing -> False
{-# INLINE isAsyncCancellation #-}
-- spec: spec/modules/Simplex/Messaging/Util.md#catchOwn
-- Catches all exceptions EXCEPT async cancellations (name is misleading)
catchOwn' :: IO a -> (E.SomeException -> IO a) -> IO a
catchOwn' action handleInternal = action `E.catch` \e -> if isAsyncCancellation e then E.throwIO e else handleInternal e
{-# INLINE catchOwn' #-}
-- spec: spec/modules/Simplex/Messaging/Util.md#catchOwn
catchOwn :: MonadUnliftIO m => m a -> (E.SomeException -> m a) -> m a
catchOwn action handleInternal =
withRunInIO $ \run ->