diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,18 @@
 # Revision history for haskell-lsp-types
 
+## 0.23.0.0
+
+* Add runWith for transporots other than stdio (@paulyoung)
+* Fix race condition in event captures (@bgamari)
+* Tweak the sectionSeparator (@alanz)
+* Add hashWithSaltInstances (@ndmitchell)
+* Fix CompletionItem.tags not being optional (@bubba)
+* Avoid unnecessary normalisation in Binary instance for
+  NormalizedFilePath (@cocreature)
+* Fix ordering of TH splices (@fendor)
+
+## 0.22.0.0
+
 * ResponseMessage results are now an Either type (@greenhat)
 * Support for GHC 8.10.1
 
diff --git a/haskell-lsp-types.cabal b/haskell-lsp-types.cabal
--- a/haskell-lsp-types.cabal
+++ b/haskell-lsp-types.cabal
@@ -1,5 +1,5 @@
 name:                haskell-lsp-types
-version:             0.22.0.0
+version:             0.23.0.0
 synopsis:            Haskell library for the Microsoft Language Server Protocol, data types
 
 description:         An implementation of the types to allow language implementors to
diff --git a/src/Language/Haskell/LSP/Types/Completion.hs b/src/Language/Haskell/LSP/Types/Completion.hs
--- a/src/Language/Haskell/LSP/Types/Completion.hs
+++ b/src/Language/Haskell/LSP/Types/Completion.hs
@@ -341,7 +341,7 @@
                        -- the text that is inserted when selecting this
                        -- completion.
     , _kind                :: Maybe CompletionItemKind
-    , _tags                :: List CompletionItemTag -- ^ Tags for this completion item.
+    , _tags                :: Maybe (List CompletionItemTag) -- ^ Tags for this completion item.
     , _detail              :: Maybe Text -- ^ A human-readable string with additional
                               -- information about this item, like type or
                               -- symbol information.
diff --git a/src/Language/Haskell/LSP/Types/DataTypesJSON.hs b/src/Language/Haskell/LSP/Types/DataTypesJSON.hs
--- a/src/Language/Haskell/LSP/Types/DataTypesJSON.hs
+++ b/src/Language/Haskell/LSP/Types/DataTypesJSON.hs
@@ -1181,8 +1181,8 @@
     | otherwise = mempty
   parseJSON _            = mempty
 
-deriveJSON lspOptions ''DidChangeWatchedFilesRegistrationOptions
 deriveJSON lspOptions ''FileSystemWatcher
+deriveJSON lspOptions ''DidChangeWatchedFilesRegistrationOptions
 
 -- ---------------------------------------------------------------------
 {-
diff --git a/src/Language/Haskell/LSP/Types/MarkupContent.hs b/src/Language/Haskell/LSP/Types/MarkupContent.hs
--- a/src/Language/Haskell/LSP/Types/MarkupContent.hs
+++ b/src/Language/Haskell/LSP/Types/MarkupContent.hs
@@ -140,7 +140,7 @@
 
 -- | Markdown for a section separator in Markdown, being a horizontal line
 sectionSeparator :: Text
-sectionSeparator = "*\t*\t*\n"
+sectionSeparator = "* * *\n"
 
 -- ---------------------------------------------------------------------
 
diff --git a/src/Language/Haskell/LSP/Types/Uri.hs b/src/Language/Haskell/LSP/Types/Uri.hs
--- a/src/Language/Haskell/LSP/Types/Uri.hs
+++ b/src/Language/Haskell/LSP/Types/Uri.hs
@@ -24,7 +24,7 @@
 import qualified Data.Aeson                                 as A
 import           Data.Binary                                (Binary, Get, put, get)
 import           Data.Hashable
-import           Data.List                                  (isPrefixOf, stripPrefix)
+import           Data.List                                  (stripPrefix)
 #if __GLASGOW_HASKELL__ < 804
 import           Data.Monoid                                ((<>))
 #endif
@@ -54,6 +54,7 @@
 
 instance Hashable NormalizedUri where
   hash (NormalizedUri h _) = h
+  hashWithSalt salt (NormalizedUri h _) = hashWithSalt salt h
 
 instance NFData NormalizedUri
 
@@ -167,23 +168,34 @@
   put (NormalizedFilePath _ fp) = put fp
   get = do
     v <- Data.Binary.get :: Get FilePath
-    return (toNormalizedFilePath v)
+    let nuri = internalNormalizedFilePathToUri v
+    return (NormalizedFilePath nuri v)
 
+-- | Internal helper that takes a file path that is assumed to
+-- already be normalized to a URI. It is up to the caller
+-- to ensure normalization.
+internalNormalizedFilePathToUri :: FilePath -> NormalizedUri
+internalNormalizedFilePathToUri fp = nuri
+  where
+    uriPath = platformAdjustToUriPath System.Info.os fp
+    nuriStr = T.pack $ fileScheme <> "//" <> uriPath
+    nuri = NormalizedUri (hash nuriStr) nuriStr
+
 instance Show NormalizedFilePath where
   show (NormalizedFilePath _ fp) = "NormalizedFilePath " ++ show fp
 
 instance Hashable NormalizedFilePath where
   hash (NormalizedFilePath uri _) = hash uri
+  hashWithSalt salt (NormalizedFilePath uri _) = hashWithSalt salt uri
 
 instance IsString NormalizedFilePath where
     fromString = toNormalizedFilePath
 
 toNormalizedFilePath :: FilePath -> NormalizedFilePath
 toNormalizedFilePath fp = NormalizedFilePath nuri nfp
-  where nfp = FP.normalise fp
-        uriPath = platformAdjustToUriPath System.Info.os nfp
-        nuriStr = T.pack $ fileScheme <> "//" <> uriPath
-        nuri = NormalizedUri (hash nuriStr) nuriStr
+  where
+      nfp = FP.normalise fp
+      nuri = internalNormalizedFilePathToUri nfp
 
 fromNormalizedFilePath :: NormalizedFilePath -> FilePath
 fromNormalizedFilePath (NormalizedFilePath _ fp) = fp
