stan-0.1.0.0: test/Test/Stan/Analysis/Common.hs
{- HLINT ignore "Eta reduce" -}
module Test.Stan.Analysis.Common
( observationAssert
, observationAssertMulti
, noObservationAssert
, itShouldStr
, unsafeNameMeta
) where
import Prelude hiding (span)
import Stan.Ghc.Compat (FastString, mkFastString, RealSrcSpan, mkRealSrcLoc, mkRealSrcSpan, srcSpanStartLine)
import System.FilePath (pathSeparator, (</>))
import Test.Hspec (Expectation, shouldBe)
import Stan.Analysis (Analysis (..))
import Stan.Core.Id (Id (..))
import Stan.Core.ModuleName (ModuleName (..))
import Stan.Inspection (Inspection (..), InspectionAnalysis (..))
import Stan.NameMeta (NameMeta, prettyShowNameMeta)
import Stan.Observation (Observation (..), mkObservationId)
import Stan.Pattern.Ast (PatternAst (..))
import qualified Data.Text as Text
{- | Checks that there's 'Observation' of a given inspection in a
given line and span.
-}
observationAssert
:: [String] -- ^ Module name
-> Analysis
-> Inspection
-> Int -- ^ Line number
-> Int -- ^ Span start
-> Int -- ^ Span end
-> Expectation
observationAssert moduleParts analysis inspection line start end =
observationAssertMulti moduleParts analysis inspection line start line end
{- | Checks that there's 'Observation' of a given inspection in a
given line and span.
-}
observationAssertMulti
:: [String] -- ^ Module name parts
-> Analysis
-> Inspection
-> Int -- ^ Start Line number
-> Int -- ^ Span start
-> Int -- ^ End Line number
-> Int -- ^ Span end
-> Expectation
observationAssertMulti
moduleParts
analysis
Inspection{..}
firstLine
start
lastLine
end
=
foundPartialObservation `shouldBe` Just expectedHeadObservation
where
foundPartialObservation :: Maybe Observation
foundPartialObservation = find
(\Observation{..} -> obsIdShort `Text.isPrefixOf` unId observationId)
(analysisObservations analysis)
expectedHeadObservation :: Observation
expectedHeadObservation = Observation
{ observationId = obsId
, observationInspectionId = inspectionId
, observationSrcSpan = span
, observationFile = path
, observationModuleName = moduleName
, observationFileContent = maybe "" observationFileContent foundPartialObservation
}
obsId :: Id Observation
obsId = mkObservationId inspectionId moduleName span
-- Prefix of Observation Id without column number, for easier testing
obsIdShort :: Text
obsIdShort = Text.takeWhile (/= ':') $ unId obsId
span :: RealSrcSpan
span = mkRealSrcSpan
(mkRealSrcLoc pathFS firstLine start)
(mkRealSrcLoc pathFS lastLine end)
path :: FilePath
path = filePathFromParts moduleParts
moduleName :: ModuleName
moduleName = moduleFromParts moduleParts
pathFS :: FastString
pathFS = mkFastString path
-- | Checks that there's no 'Observation' of a given inspection in a given line.
noObservationAssert
:: [String] -- ^ Module parts
-> Analysis
-> Inspection
-> Int -- ^ Line number
-> Expectation
noObservationAssert parts analysis Inspection{..} line =
foundPartialObservation `shouldBe` Nothing
where
foundPartialObservation :: Maybe Observation
foundPartialObservation = find
(\Observation{..} ->
observationInspectionId == inspectionId
&& observationFile == filePathFromParts parts
&& observationModuleName == moduleFromParts parts
&& srcSpanStartLine observationSrcSpan == line
)
(analysisObservations analysis)
filePathFromParts :: [String] -> FilePath
filePathFromParts parts =
"target" </> "Target" </> intercalate [pathSeparator] parts <> ".hs"
moduleFromParts :: [String] -> ModuleName
moduleFromParts parts = ModuleName $ toText $ "Target." <> intercalate "." parts
-- | Generates text to be used in tests names.
itShouldStr :: Inspection -> String
itShouldStr Inspection{..} = toString $ unId inspectionId
<> ": finds usage of '"
<> prettyShowNameMeta (unsafeNameMeta inspectionAnalysis)
<> "'"
unsafeNameMeta :: InspectionAnalysis -> NameMeta
unsafeNameMeta (FindAst (PatternAstName nm _)) = nm
unsafeNameMeta (FindAst (PatternAstOr (PatternAstName nm _) _)) = nm
unsafeNameMeta _ = error "Impossible happened in tests"