Start cleaning up pretty-print (#821)

* Move from prettyDiagnostic to prettyDiagnostics

* Remove as much pretty print stuff as we can

* Try moving duplicate named functions with similar semantics and identical types to different names

* Change to returning pretty printed outputs from Diagnostics

* Remove a redundant import
This commit is contained in:
Neil Mitchell 2019-05-01 19:06:00 +01:00 committed by GitHub
parent 56c322c982
commit 4040dffc7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 51 additions and 216 deletions

View File

@ -24,8 +24,8 @@ module Development.IDE.Types.Diagnostics (
ideErrorPretty,
errorDiag,
ideTryIOException,
prettyFileDiagnostics,
prettyDiagnostic,
showDiagnostics,
showDiagnosticsColored,
prettyDiagnosticStore,
defDiagnostic,
addDiagnostics,
@ -162,35 +162,45 @@ type FileDiagnostics = (Uri, [Diagnostic])
prettyRange :: Range -> Doc SyntaxClass
prettyRange Range{..} =
label_ "Range" $ vcat
[ label_ "Start:" $ prettyPosition _start
, label_ "End: " $ prettyPosition _end
slabel_ "Range" $ vcat
[ slabel_ "Start:" $ prettyPosition _start
, slabel_ "End: " $ prettyPosition _end
]
prettyPosition :: Position -> Doc SyntaxClass
prettyPosition Position{..} = label_ "Position" $ vcat
[ label_ "Line:" $ pretty _line
, label_ "Character:" $ pretty _character
prettyPosition Position{..} = slabel_ "Position" $ vcat
[ slabel_ "Line:" $ pretty _line
, slabel_ "Character:" $ pretty _character
]
stringParagraphs :: T.Text -> Doc a
stringParagraphs = vcat . map (fillSep . map pretty . T.words) . T.lines
showDiagnostics :: [LSP.Diagnostic] -> T.Text
showDiagnostics = srenderPlain . prettyDiagnostics
showDiagnosticsColored :: [LSP.Diagnostic] -> T.Text
showDiagnosticsColored = srenderColored . prettyDiagnostics
prettyDiagnostics :: [LSP.Diagnostic] -> Doc SyntaxClass
prettyDiagnostics = vcat . map prettyDiagnostic
prettyDiagnostic :: LSP.Diagnostic -> Doc SyntaxClass
prettyDiagnostic LSP.Diagnostic{..} =
vcat
[label_ "Range: "
[slabel_ "Range: "
$ prettyRange _range
, label_ "Source: " $ pretty _source
, label_ "Severity:" $ pretty $ show sev
, label_ "Message: "
, slabel_ "Source: " $ pretty _source
, slabel_ "Severity:" $ pretty $ show sev
, slabel_ "Message: "
$ case sev of
LSP.DsError -> annotate ErrorSC
LSP.DsWarning -> annotate WarningSC
LSP.DsInfo -> annotate InfoSC
LSP.DsHint -> annotate HintSC
$ stringParagraphs _message
, label_ "Code:" $ pretty _code
, slabel_ "Code:" $ pretty _code
]
where
sev = fromMaybe LSP.DsError _severity
@ -204,18 +214,18 @@ prettyDiagnosticStore ds =
prettyFileDiagnostics :: FileDiagnostics -> Doc SyntaxClass
prettyFileDiagnostics (uri, diags) =
label_ "Compiler error in" $ vcat
[ label_ "File:" $ pretty filePath
, label_ "Errors:" $ vcat $ map prettyDiagnostic diags
slabel_ "Compiler error in" $ vcat
[ slabel_ "File:" $ pretty filePath
, slabel_ "Errors:" $ vcat $ map prettyDiagnostic diags
] where
-- prettyFileDiags :: (FilePath, [(T.Text, [LSP.Diagnostic])]) -> Doc SyntaxClass
-- prettyFileDiags (fp,stages) =
-- label_ ("File: "<>fp) $ vcat $ map prettyStage stages
-- slabel_ ("File: "<>fp) $ vcat $ map prettyStage stages
-- prettyStage :: (T.Text, [LSP.Diagnostic]) -> Doc SyntaxClass
-- prettyStage (stage,diags) =
-- label_ ("Stage: "<>T.unpack stage) $ vcat $ map prettyDiagnostic diags
-- slabel_ ("Stage: "<>T.unpack stage) $ vcat $ map prettyDiagnostic diags
filePath :: FilePath
filePath = fromMaybe dontKnow $ uriToFilePath uri

View File

@ -479,9 +479,6 @@ prettyContractId :: TL.Text -> Doc SyntaxClass
prettyContractId coid =
linkToIdSC ("n" <> TL.toStrict coid) $ char '#' <> ltext coid
-- commentSC :: EmbedsSyntaxClass a => Doc SyntaxClass -> Doc SyntaxClass
-- commentSC = annotateSC CommentSC -- White
linkSC :: T.Text -> T.Text -> Doc SyntaxClass -> Doc SyntaxClass
linkSC url title = annotateSC (LinkSC url title)

View File

@ -16,7 +16,6 @@ import DA.Daml.GHC.Damldoc.Transform
import qualified DA.Service.Daml.Compiler.Impl.Handle as DGHC
import DA.Daml.GHC.Compiler.Options
import qualified Data.Text.Prettyprint.Doc.Syntax as Pretty
import Development.IDE.Types.Diagnostics
import Control.Monad.Extra
@ -49,7 +48,7 @@ damlDocDriver cInputFormat output cFormat prefixFile options files = do
let onErrorExit act =
act >>= either (printAndExit . renderDiags) pure
renderDiags = T.unpack . Pretty.renderColored . Pretty.vcat . map prettyDiagnostic
renderDiags = T.unpack . showDiagnosticsColored
docData <- case cInputFormat of
InputJson -> do

View File

@ -15,8 +15,6 @@ module DA.Test.GHC
import DA.Daml.GHC.Compiler.Options
import DA.Daml.GHC.Compiler.UtilLF
import qualified Data.Text.Prettyprint.Doc.Syntax as Pretty
import DA.Daml.LF.Ast as LF hiding (IsTest)
import "ghc-lib-parser" UniqSupply
import "ghc-lib-parser" Unique
@ -201,7 +199,7 @@ data DiagnosticField
checkDiagnostics :: (String -> IO ()) -> [[DiagnosticField]] -> [D.Diagnostic] -> IO (Maybe String)
checkDiagnostics log expected got = do
when (got /= []) $
log $ T.unpack $ Pretty.renderPlain $ Pretty.vcat $ map prettyDiagnostic got
log $ T.unpack $ showDiagnostics got
-- you require the same number of diagnostics as expected
-- and each diagnostic is at least partially expected

View File

@ -42,7 +42,6 @@ import qualified Data.Set as Set
import qualified Data.List.Split as Split
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Text.Prettyprint.Doc.Syntax as Pretty
import Development.IDE.Types.Diagnostics
import GHC.Conc
import qualified Network.Socket as NS
@ -282,8 +281,7 @@ execPackageNew numProcessors mbOutFile =
unlines
[ "Creation of DAR file failed:"
, T.unpack $
Pretty.renderColored $
Pretty.vcat $ map prettyDiagnostic errs
showDiagnosticsColored errs
]
Right dar -> do
let fp = targetFilePath pName
@ -414,9 +412,7 @@ execPackage filePath opts mbOutFile dumpPom dalfInput = withProjectRoot $ \relat
Left errs
-> ioError $ userError $ unlines
[ "Creation of DAR file failed:"
, T.unpack $ Pretty.renderColored
$ Pretty.vcat
$ map prettyDiagnostic
, T.unpack $ showDiagnosticsColored
$ Set.toList $ Set.fromList errs ]
Right dar -> do
createDirectoryIfMissing True $ takeDirectory targetFilePath

View File

@ -83,7 +83,7 @@ failedTestOutput :: IdeState -> FilePath -> CompilerService.Action [(VirtualReso
failedTestOutput h file = do
mbScenarioNames <- CompilerService.getScenarioNames file
diagnostics <- liftIO $ CompilerService.getDiagnostics h
let errMsg = T.unlines (map (Pretty.renderPlain . prettyDiagnostic) diagnostics)
let errMsg = showDiagnostics diagnostics
pure $ map (, Just errMsg) $ fromMaybe [VRScenario file "Unknown"] mbScenarioNames

View File

@ -15,7 +15,6 @@ import qualified Data.Text as T
import qualified Data.Text.IO as T
import Development.IDE.Types.Diagnostics
import Data.List.Extra
import qualified Data.Text.Prettyprint.Doc.Syntax as Pretty
import System.IO (Handle, hClose, hPutStr, stdout, openFile, IOMode (WriteMode))
import Control.Exception (bracket)
@ -54,10 +53,9 @@ reportErr msg errs =
unlines
[ msg
, T.unpack $
Pretty.renderColored $
Pretty.vcat $ map prettyDiagnostic $ nubOrd errs
showDiagnosticsColored $ nubOrd errs
]
printDiagnostics :: [Diagnostic] -> IO ()
printDiagnostics [] = return ()
printDiagnostics xs = T.putStrLn $ Pretty.renderColored $ Pretty.vcat $ map prettyDiagnostic xs
printDiagnostics xs = T.putStrLn $ showDiagnosticsColored xs

View File

@ -18,21 +18,10 @@ module DA.Pretty
-- * Convenience re-export
module Text.PrettyPrint.Annotated.Extended
-- ** Bytestring combinators
, byteStringBase64
, byteStringUtf8Decoded
-- ** List combinators
, numbered
, numberedNOutOf
, bracketedList
, bracketedSemicolonList
, bracedList, vbracedList
, angledList, vangledList
, parallelBracedList
, angledList
, fcommasep
, PrettyLevel(..)
, Pretty(..)
, prettyNormal
, pretty
@ -49,44 +38,21 @@ module DA.Pretty
-- * Syntax-highlighted html support
, renderHtmlDocumentText
, renderHtmlDocument
, renderHtmlDocumentWithStyleText
, renderHtmlDocumentWithStyle
, renderHtml
, highlightStylesheet
, highlightClass
-- ** Annotation combinators
, comment_
, predicate_
, operator_
, error_
, warning_
, type_
, typeDoc_
, keyword_
, label_
, paren_
-- ** Comment combinators
, lineComment
, lineComment_
, multiComment
-- Utilities
, prettyText
, toPrettyprinter
) where
import qualified Data.ByteString.Base64.URL as Base64.Url
import qualified Data.ByteString.Char8 as BC8
import Data.String
import qualified Data.Text.Extended as T
import qualified Data.Text.Encoding as TE
import DA.Prelude
@ -105,13 +71,7 @@ import System.Console.ANSI
)
import Data.Text.Prettyprint.Doc.Syntax (SyntaxClass(..))
import qualified Data.Text.Prettyprint.Doc.Syntax as Prettyprinter
-- | Adapter to ease migration to prettyprinter. This drops all annotations.
toPrettyprinter :: Pretty a => a -> Prettyprinter.Doc ann
toPrettyprinter a =
Prettyprinter.concatWith (\x y -> x <> Prettyprinter.hardline <> y) $
fmap Prettyprinter.pretty $ T.splitOn "\n" (renderPlain $ pretty a :: T.Text)
------------------------------------------------------------------------------
-- Types and classes to organize pretty-pringing
@ -203,18 +163,14 @@ renderColored doc =
handleAnn ann = case ann of
OperatorSC -> CSNode (Dull, Red)
KeywordSC -> CSNode (Dull, Green)
ParensSC -> CSNode (Dull, Yellow)
CommentSC -> CSNode (Dull, White)
PredicateSC -> CSNode (Dull, Magenta)
ConstructorSC -> CSNode (Vivid, Blue)
ProofStepSC -> CSNode (Dull, Blue)
TypeSC -> CSNode (Vivid, Green)
ErrorSC -> CSNode (Vivid, Red)
WarningSC -> CSNode (Vivid, Yellow)
HintSC -> CSNode (Vivid, Blue)
InfoSC -> CSNode (Vivid, Magenta)
LinkSC _ _ -> CSNode (Vivid, Green)
NoAnnotationSC -> id
IdSC _ -> id
OnClickSC _ -> id
@ -238,9 +194,6 @@ renderPlainOneLine = renderStyle (defaultStyle { mode = OneLineMode })
-- How many chars should be at most in a rendered line?
type LineWidth = Int
-- What style should be used for the body?
type BodyStyle = T.Text
-- Use the standard DA colors for highlighting
cssStyle :: H.Html
cssStyle = H.style $ H.text highlightStylesheet
@ -256,17 +209,6 @@ renderHtmlDocument lineWidth doc =
H.docTypeHtml $ H.head cssStyle <> (H.body H.! A.class_ (H.textValue highlightClass) $ renderHtml lineWidth doc)
-- Render a whole 'H.Html' document with DA colors for highlighting to 'T.Text'
renderHtmlDocumentWithStyleText :: LineWidth -> BodyStyle -> Doc SyntaxClass -> T.Text
renderHtmlDocumentWithStyleText lineWidth style =
T.pack . BlazeRenderer.renderHtml . renderHtmlDocumentWithStyle lineWidth style
renderHtmlDocumentWithStyle :: LineWidth -> BodyStyle -> Doc SyntaxClass -> H.Html
renderHtmlDocumentWithStyle lineWidth style doc =
H.docTypeHtml $ H.head cssStyle
<> (H.body H.! A.class_ (H.textValue highlightClass) H.! A.style (H.textValue style))
(renderHtml lineWidth doc)
-- | Render one of our documents to 'H.Html'
renderHtml
:: LineWidth
@ -281,14 +223,10 @@ renderHtml lineWidth =
-- | Apply a syntax-class annotation.
applySyntaxClass :: SyntaxClass -> H.Html -> H.Html
applySyntaxClass = \case
NoAnnotationSC -> id
OperatorSC -> apply "operator"
KeywordSC -> apply "keyword"
ParensSC -> apply "parens"
PredicateSC -> apply "predicate"
ConstructorSC -> apply "constructor"
ProofStepSC -> apply "proof-step"
CommentSC -> apply "comment"
TypeSC -> apply "type"
WarningSC -> apply "warning"
ErrorSC -> apply "error"
@ -328,24 +266,9 @@ prettyCharToHtml = prettyStringToHtml . return
-- Additional generic combinators
------------------------------------------------------------------------------
-- | The default 'B.ByteString' encoding, which is guaranteed to be parseable.
byteStringBase64 :: BC8.ByteString -> Doc a
byteStringBase64 bs = string $ "0b64." ++ (BC8.unpack $ Base64.Url.encode bs)
-- | A more reable 'B.ByteString' pretty-printing, which tries to perform
-- UTF-8 decoding and falls back to 'byteStringBase64' if that fails.
byteStringUtf8Decoded :: BC8.ByteString -> Doc a
byteStringUtf8Decoded bs =
case TE.decodeUtf8' bs of
Left _unicodeExc -> byteStringBase64 bs
Right t -> fsep $ map text $ T.lines t
annotateSC :: SyntaxClass -> Doc SyntaxClass -> Doc SyntaxClass
annotateSC = annotate
comment_ :: Doc SyntaxClass -> Doc SyntaxClass
comment_ = annotateSC CommentSC
type_ :: String -> Doc SyntaxClass
type_ = typeDoc_ . string
@ -355,108 +278,32 @@ typeDoc_ = annotateSC TypeSC
operator_ :: String -> Doc SyntaxClass
operator_ = annotateSC OperatorSC . string
predicate_ :: String -> Doc SyntaxClass
predicate_ = annotateSC PredicateSC . string
keyword_ :: String -> Doc SyntaxClass
keyword_ = annotateSC KeywordSC . string
paren_ :: Doc SyntaxClass -> Doc SyntaxClass
paren_ = annotateSC ParensSC
error_ :: Doc SyntaxClass -> Doc SyntaxClass
error_ = annotateSC ErrorSC
warning_ :: Doc SyntaxClass -> Doc SyntaxClass
warning_ = annotateSC WarningSC
-- | Pretty print a list of documents with prefixed bracs and commas.
bracedList :: [Doc a] -> Doc a
bracedList = prefixedList lbrace rbrace ","
-- | Pretty print a list of documents with prefixed bracs and commas.
angledList :: [Doc a] -> Doc a
angledList = prefixedList "<" ">" ","
-- | Pretty print a list of documents with prefixed '{|' braces and commas.
parallelBracedList :: [Doc a] -> Doc a
parallelBracedList = prefixedList "{|" "|}" " |"
bracketedList :: [Doc a] -> Doc a
bracketedList = prefixedList lbrack rbrack ","
bracketedSemicolonList :: [Doc a] -> Doc a
bracketedSemicolonList = prefixedList lbrack rbrack ";"
-- | Generic combinator for prefixing a list with delimiters and commas.
prefixedList :: Doc a -> Doc a -> Doc a -> [Doc a] -> Doc a
prefixedList leftParen rightParen separator = \case
[] -> leftParen <-> rightParen
(d:ds) -> sep [cat (leftParen <-> d : map (separator <->) ds), rightParen]
-- | A 'braced-list whose elements are vertically concatenated with empty lines.
vbracedList :: [Doc a] -> Doc a
vbracedList [] = string "{ }"
vbracedList (d:ds) = vsep (lbrace <-> d : map (comma <->) ds) $-$ rbrace
-- | An 'angled-list whose elements are vertically concatenated with empty lines.
vangledList :: [Doc a] -> Doc a
vangledList [] = string "< >"
vangledList (d:ds) = vsep ("<" <-> d : map (comma <->) ds) $-$ ">"
-- | Pretty print a list of values as a comma-separated list wrapped in
-- paragraph mode.
fcommasep :: [Doc a] -> Doc a
fcommasep = fsep . punctuate comma
-- | Pretty-print a list of documents with prefixed numbers.
numbered :: [Doc a] -> Doc a
numbered docs =
vcat $ zipWith pp [(1::Int)..] docs
where
n = length docs
nString = show n
padding = length nString
pad cs = replicate (max 0 (padding - length cs)) ' ' <> cs
showNumber i = pad (show i) <> "."
indent = length (showNumber n) + 1
pp i doc = string (showNumber i) $$ nest indent doc
-- | Pretty-print a list of documents with prefixed numbers in the style of
-- @i/n@.
numberedNOutOf :: [Doc a] -> Doc a
numberedNOutOf docs =
vcat $ zipWith pp [(1::Int)..] docs
where
n = length docs
nString = show n
padding = length nString
pad cs = replicate (max 0 (padding - length cs)) ' ' <> cs
showNumber i = pad (show i) <> "/" <> nString
indent = length (showNumber n) + 1
pp i doc = string (showNumber i) $-$ nest indent doc
-- | Label a document.
label_ :: String -> Doc a -> Doc a
label_ t d = sep [string t, nest 2 d]
------------------------------------------------------------------------------
-- Comments
------------------------------------------------------------------------------
lineComment :: Doc SyntaxClass -> Doc SyntaxClass
lineComment d = comment_ $ string "//" <-> d
lineComment_ :: String -> Doc SyntaxClass
lineComment_ = lineComment . string
multiComment :: Doc SyntaxClass -> Doc SyntaxClass
multiComment d = comment_ $ fsep [string "/*", d, string "*/"]
prettyText :: Pretty a => a -> T.Text
prettyText = T.pack . renderPlain . pretty
------------------------------------------------------------------------------
--- Embedded stylesheets
------------------------------------------------------------------------------
@ -483,4 +330,3 @@ highlightStylesheet = "\
\.da-hl-proof-step { color: var(--vscode-terminal-ansiBlue); } \
\.da-hl-link { color: var(--link-color); text-decoration: underline; cursor: pointer; } \
\.da-hl-nobr { white-space: pre; }"

View File

@ -4,31 +4,29 @@
module Data.Text.Prettyprint.Doc.Syntax
( module Data.Text.Prettyprint.Doc
, SyntaxClass(..)
, label_
, comment_
, reflow
, renderPlain
, renderColored
-- prefixing these names with an 's' is not pleasant
-- but we have duplicates of the functions with identical signatures
-- and different semantics at DA.Pretty, so important to try and disambiguate
, slabel_
, srenderPlain
, srenderColored
) where
import Data.Text.Prettyprint.Doc
import Data.Text.Prettyprint.Doc.Render.Text
import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Terminal
import Data.Text.Prettyprint.Doc.Render.Terminal (Color(..), color, colorDull)
import Data.Text.Prettyprint.Doc.Util
import Data.Text.Prettyprint.Doc.Util(reflow)
import qualified Data.Text as T
-- | Classes of syntax elements, which are used for highlighting.
data SyntaxClass
= NoAnnotationSC
-- ^ Annotation to use as a no-op for highlighting.
| OperatorSC
= -- ^ Annotation to use as a no-op for highlighting.
OperatorSC
| KeywordSC
| ParensSC
| PredicateSC
| ConstructorSC
| CommentSC
| ProofStepSC
| TypeSC
| ErrorSC
| WarningSC
@ -42,11 +40,8 @@ data SyntaxClass
deriving (Eq, Ord, Show)
-- | Label a document.
label_ :: String -> Doc a -> Doc a
label_ t d = nest 2 $ sep [pretty t, d]
comment_ :: Doc SyntaxClass -> Doc SyntaxClass
comment_ = annotate CommentSC
slabel_ :: String -> Doc a -> Doc a
slabel_ t d = nest 2 $ sep [pretty t, d]
-- | The layout options used for the SDK assistant.
cliLayout ::
@ -58,12 +53,12 @@ cliLayout renderWidth = LayoutOptions
}
-- | Render without any syntax annotations
renderPlain :: Doc ann -> T.Text
renderPlain = renderStrict . layoutSmart (cliLayout defaultTermWidth)
srenderPlain :: Doc ann -> T.Text
srenderPlain = renderStrict . layoutSmart (cliLayout defaultTermWidth)
-- | Render a 'Document' as an ANSII colored string.
renderColored :: Doc SyntaxClass -> T.Text
renderColored =
srenderColored :: Doc SyntaxClass -> T.Text
srenderColored =
Terminal.renderStrict .
layoutSmart defaultLayoutOptions { layoutPageWidth = AvailablePerLine 100 1.0 } .
fmap toAnsiStyle
@ -71,18 +66,14 @@ renderColored =
toAnsiStyle ann = case ann of
OperatorSC -> colorDull Red
KeywordSC -> colorDull Green
ParensSC -> colorDull Yellow
CommentSC -> colorDull White
PredicateSC -> colorDull Magenta
ConstructorSC -> color Blue
ProofStepSC -> colorDull Blue
TypeSC -> color Green
ErrorSC -> color Red
WarningSC -> color Yellow
InfoSC -> color Blue
HintSC -> color Magenta
LinkSC _ _ -> color Green
NoAnnotationSC -> mempty
IdSC _ -> mempty
OnClickSC _ -> mempty