{-# OPTIONS_GHC -Wall #-} {-# LANGUAGE OverloadedStrings #-} module Reporting.Error.Docs ( Error(..) , SyntaxProblem(..) , NameProblem(..) , DefProblem(..) , toReports ) where import qualified Data.Name as Name import qualified Data.NonEmptyList as NE import Parse.Primitives (Row, Col) import Parse.Symbol (BadOperator(..)) import qualified Reporting.Annotation as A import Reporting.Doc ((<>)) import qualified Reporting.Doc as D import qualified Reporting.Render.Code as Code import qualified Reporting.Error.Syntax as E import qualified Reporting.Report as Report data Error = NoDocs A.Region | ImplicitExposing A.Region | SyntaxProblem SyntaxProblem | NameProblems (NE.List NameProblem) | DefProblems (NE.List DefProblem) data SyntaxProblem = Op Row Col | OpBad BadOperator Row Col | Name Row Col | Space E.Space Row Col | Comma Row Col | BadEnd Row Col data NameProblem = NameDuplicate Name.Name A.Region A.Region | NameOnlyInDocs Name.Name A.Region | NameOnlyInExports Name.Name A.Region data DefProblem = NoComment Name.Name A.Region | NoAnnotation Name.Name A.Region -- TO REPORTS toReports :: Code.Source -> Error -> NE.List Report.Report toReports source err = case err of NoDocs region -> NE.singleton $ Report.Report "NO DOCS" region [] $ Code.toSnippet source region Nothing ( D.reflow $ "You must have a documentation comment between the module\ \ declaration and the imports." , D.reflow "Learn more at " ) ImplicitExposing region -> NE.singleton $ Report.Report "IMPLICIT EXPOSING" region [] $ Code.toSnippet source region Nothing ( D.reflow $ "I need you to be explicit about what this module exposes:" , D.reflow $ "A great API usually hides some implementation details, so it is rare that\ \ everything in the file should be exposed. And requiring package authors\ \ to be explicit about this is a way of adding another quality check before\ \ code gets published. So as you write out the public API, ask yourself if\ \ it will be easy to understand as people read the documentation!" ) SyntaxProblem problem -> NE.singleton $ toSyntaxProblemReport source problem NameProblems problems -> fmap (toNameProblemReport source) problems DefProblems problems -> fmap (toDefProblemReport source) problems -- SYNTAX PROBLEM toSyntaxProblemReport :: Code.Source -> SyntaxProblem -> Report.Report toSyntaxProblemReport source problem = let toSyntaxReport row col details = let region = toRegion row col in Report.Report "PROBLEM IN DOCS" region [] $ Code.toSnippet source region Nothing ( D.reflow "I was partway through parsing your module documentation, but I got stuck here:" , D.stack $ [ D.reflow details , D.toSimpleHint $ "Read through https://package.elm-lang.org/help/documentation-format for\ \ tips on how to write module documentation!" ] ) in case problem of Op row col -> toSyntaxReport row col $ "I am trying to parse an operator like (+) or (*) but something is going wrong." OpBad _ row col -> toSyntaxReport row col $ "I am trying to parse an operator like (+) or (*) but it looks like you are using\ \ a reserved symbol in this case." Name row col -> toSyntaxReport row col $ "I was expecting to see the name of another exposed value from this module." Space space row col -> E.toSpaceReport source space row col Comma row col -> toSyntaxReport row col $ "I was expecting to see a comma next." BadEnd row col -> toSyntaxReport row col $ "I am not really sure what I am getting stuck on though." toRegion :: Row -> Col -> A.Region toRegion row col = let pos = A.Position row col in A.Region pos pos -- NAME PROBLEM toNameProblemReport :: Code.Source -> NameProblem -> Report.Report toNameProblemReport source problem = case problem of NameDuplicate name r1 r2 -> Report.Report "DUPLICATE DOCS" r2 [] $ Code.toPair source r1 r2 ( D.reflow $ "There can only be one `" <> Name.toChars name <> "` in your module documentation, but it is listed twice:" , "Remove one of them!" ) ( D.reflow $ "There can only be one `" <> Name.toChars name <> "` in your module documentation, but I see two. One here:" , "And another one over here:" , "Remove one of them!" ) NameOnlyInDocs name region -> Report.Report "DOCS MISTAKE" region [] $ Code.toSnippet source region Nothing ( D.reflow $ "I do not see `" <> Name.toChars name <> "` in the `exposing` list, but it is in your module documentation:" , D.reflow $ "Does it need to be added to the `exposing` list as well? Or maybe you removed `" <> Name.toChars name <> "` and forgot to delete it here?" ) NameOnlyInExports name region -> Report.Report "DOCS MISTAKE" region [] $ Code.toSnippet source region Nothing ( D.reflow $ "I do not see `" <> Name.toChars name <> "` in your module documentation, but it is in your `exposing` list:" , D.stack [ D.reflow $ "Add a line like `@docs " <> Name.toChars name <> "` to your module documentation!" , D.link "Note" "See" "docs" "for more guidance on writing high quality docs." ] ) -- DEF PROBLEM toDefProblemReport :: Code.Source -> DefProblem -> Report.Report toDefProblemReport source problem = case problem of NoComment name region -> Report.Report "NO DOCS" region [] $ Code.toSnippet source region Nothing ( D.reflow $ "The `" <> Name.toChars name <> "` definition does not have a documentation comment." , D.stack [ D.reflow $ "Add documentation with nice examples of how to use it!" , D.link "Note" "Read" "docs" "for more advice on writing great docs. There are a couple important tricks!" ] ) NoAnnotation name region -> Report.Report "NO TYPE ANNOTATION" region [] $ Code.toSnippet source region Nothing ( D.reflow $ "The `" <> Name.toChars name <> "` definition does not have a type annotation." , D.stack [ D.reflow $ "I use the type variable names from your annotations when generating docs. So if\ \ you say `Html msg` in your type annotation, I can use `msg` in the docs and make\ \ them a bit clearer. So add an annotation and try to use nice type variables!" , D.link "Note" "Read" "docs" "for more advice on writing great docs. There are a couple important tricks!" ] )