22{-# LANGUAGE QuasiQuotes #-}
33module GHC.DiagnosticSpec (spec ) where
44
5- import Data.ByteString qualified as B
65import Helper hiding (diagnostic )
76import Test.Hspec.Expectations.Contrib qualified as Hspec
87import Text.RawString.QQ (r , rQ )
@@ -11,11 +10,12 @@ import System.Process
1110import System.Environment
1211import qualified Data.Text as T
1312import qualified Data.Text.Encoding as T
13+ import Data.ByteString qualified as B
14+ import qualified Data.Map as Map
1415
1516import Language.Haskell.GhciWrapper (lookupGhc )
1617import GHC.Diagnostic
1718import GHC.Diagnostic.Annotated
18- import qualified Data.Map as Map
1919
2020data Requirement = NoRequirement | RequireGhc912
2121
@@ -33,15 +33,8 @@ _ignore = let _ = (ftest, xtest) in ()
3333normalizeGhcVersion :: String -> String
3434normalizeGhcVersion = T. unpack . T. replace __GLASGOW_HASKELL_FULL_VERSION__ " 9.10.0" . T. pack
3535
36- availableImports :: AvailableImports
37- availableImports = Map. fromList [
38- (" c2w" , [" Data.ByteString.Internal" ])
39- , (" fromList" , [" Data.Map" ])
40- ]
41-
42-
4336testWith :: HasCallStack => FilePath -> Requirement -> [String ] -> String -> Maybe Annotation -> [Solution ] -> Spec
44- testWith name requirement extraArgs (unindent -> code) action solutions = it name $ do
37+ testWith name requirement extraArgs (unindent -> code) annotation solutions = it name do
4538 unless (T. null code) do
4639 ensureFile src $ T. encodeUtf8 code
4740 err <- translate <$> ghc [" -fno-diagnostics-show-caret" ]
@@ -50,9 +43,9 @@ testWith name requirement extraArgs (unindent -> code) action solutions = it nam
5043 ensureFile (dir </> " err.json" ) (encodeUtf8 $ normalizeGhcVersion json)
5144 Hspec. annotate (separator <> err <> separator) do
5245 Just annotated <- return . parseAnnotated availableImports $ encodeUtf8 json
53- when shouldRun $ do
46+ when shouldRun do
5447 format annotated. diagnostic `shouldBe` err
55- annotated. annotation `shouldBe` action
48+ annotated. annotation `shouldBe` annotation
5649 annotated. solutions `shouldBe` solutions
5750 where
5851 separator :: String
@@ -90,6 +83,12 @@ testWith name requirement extraArgs (unindent -> code) action solutions = it nam
9083 True
9184#endif
9285
86+ availableImports :: AvailableImports
87+ availableImports = Map. fromList [
88+ (" c2w" , [" Data.ByteString.Internal" ])
89+ , (" fromList" , [" Data.Map" ])
90+ ]
91+
9392unindent :: String -> Text
9493unindent (T. pack >>> T. dropWhileEnd isSpace >>> T. lines -> input) = go input
9594 where
@@ -102,58 +101,38 @@ unindent (T.pack >>> T.dropWhileEnd isSpace >>> T.lines -> input) = go input
102101 dropEmptyLines :: [Text ] -> [Text ]
103102 dropEmptyLines = filter (not . T. all isSpace)
104103
105- variableNotInScope :: RequiredVariable -> Maybe Annotation
106- variableNotInScope name = Just $ NotInScope name
107-
108104redundantImport :: Maybe Annotation
109105redundantImport = Just RedundantImport
110106
111- suggestImport :: Module -> Text -> Solution
112- suggestImport module_ name = ImportName module_ Unqualified name
107+ notInScope :: RequiredVariable -> Maybe Annotation
108+ notInScope = Just . NotInScope
109+
110+ importName :: Module -> Text -> Solution
111+ importName module_ = ImportName module_ Unqualified
113112
114113spec :: Spec
115114spec = do
116- describe " format" $ do
115+ describe " format" do
117116 test " not-in-scope" [] [r |
118117 module Foo where
119118 foo = c2w
120- |] (variableNotInScope " c2w" ) [suggestImport " Data.ByteString.Internal" " c2w" ]
121-
122- test " not-in-scope-type-signature" [] [r |
123- module Foo where
124- foo :: String -> String -> String -> String -> String -> String -> String
125- foo = c2w
126- |] (variableNotInScope $ RequiredVariable Unqualified " c2w" $ Just " String -> String -> String -> String -> String -> String -> String" ) [suggestImport " Data.ByteString.Internal" " c2w" ]
127-
128- test " not-in-scope-qualified" [] [r |
129- module Foo where
130- foo = B.c2w
131- |] (variableNotInScope $ RequiredVariable " B" " c2w" Nothing ) [ImportName " Data.ByteString.Internal" (Qualified " B" ) " c2w" ]
132-
133- test " not-in-scope-qualified-2" [] [r |
134- module Foo where
135- import Data.List.NonEmpty qualified as Ma
136- foo = Map.fromList
137- |] (variableNotInScope $ RequiredVariable " Map" " fromList" Nothing ) [
138- UseName " Ma.fromList"
139- , ImportName " Data.Map" (Qualified " Map" ) " fromList"
140- ]
119+ |] (notInScope " c2w" ) [importName " Data.ByteString.Internal" " c2w" ]
141120
142121 test " not-in-scope-perhaps-use" [] [r |
143122 module Foo where
144123 foo = filter_
145- |] (variableNotInScope " filter_" ) [UseName " filter" ]
124+ |] (notInScope " filter_" ) [UseName " filter" ]
146125
147126 test " not-in-scope-perhaps-use-one-of-these" [] [r |
148127 module Foo where
149128 foo = fold
150- |] (variableNotInScope " fold" ) [UseName " foldl" , UseName " foldr" ]
129+ |] (notInScope " fold" ) [UseName " foldl" , UseName " foldr" ]
151130
152131 test " not-in-scope-perhaps-use-multiline" [] [r |
153132 module Foo where
154133 import Data.List
155134 foo = fold
156- |] (variableNotInScope " fold" ) [UseName " foldl" , UseName " foldr" ]
135+ |] (notInScope " fold" ) [UseName " foldl" , UseName " foldr" ]
157136
158137 test " use-BlockArguments" [] [r |
159138 {-# LANGUAGE NoBlockArguments #-}
@@ -194,28 +173,29 @@ spec = do
194173 foo = "foo" + 23
195174 |] Nothing []
196175
197- describe " extractIdentifiers" $ do
198- it " extracts identifiers" $ do
176+ describe " extractIdentifiers" do
177+ it " extracts identifiers" do
199178 extractIdentifiers " .. `foldl' ..., `foldr' .." `shouldBe` [UseName " foldl" , UseName " foldr" ]
200179
201- describe " qualifiedName" $ do
202- it " " do
180+ describe " qualifiedName" do
181+ it " parses an unqualified name " do
203182 qualifiedName " foo" `shouldBe` RequiredVariable Unqualified " foo" Nothing
183+
184+ it " parses a qualified name" do
204185 qualifiedName " Foo.Bar.baz" `shouldBe` RequiredVariable " Foo.Bar" " baz" Nothing
205186
206- describe " formatAnnotated" $ do
207- it " extracts identifiers" $ do
208- err <- B. readFile " test/fixtures/not-in-scope/err.json"
209- Just foo <- return $ parseAnnotated availableImports err
210- formatAnnotated foo `shouldBe` T. unlines [
187+ describe " formatAnnotated" do
188+ it " formats an annotated diagnostic message" do
189+ Just annotated <- B. readFile " test/fixtures/not-in-scope/err.json" <&> parseAnnotated availableImports
190+ formatAnnotated annotated `shouldBe` T. unlines [
211191 " test/fixtures/not-in-scope/Foo.hs:2:7: error: [GHC-88464]"
212192 , " Variable not in scope: c2w"
213193 , " "
214194 , T. pack (withColor Cyan " [1] " ) <> " import Data.ByteString.Internal (c2w)"
215195 ]
216196
217- describe " applyReplace" $ do
218- it " replaces a given source span with a substitute" $ do
197+ describe " applyReplace" do
198+ it " replaces a given source span with a substitute" do
219199 applyReplace (Location 2 7 ) (Location 2 14 ) " filter" [
220200 " module Foo where"
221201 , " foo = filter_ p xs"
@@ -224,7 +204,7 @@ spec = do
224204 , " foo = filter p xs"
225205 ]
226206
227- it " correctly handles source spans that span over multiple lines" $ do
207+ it " correctly handles source spans that span over multiple lines" do
228208 applyReplace (Location 2 8 ) (Location 3 7 ) " Ya" [
229209 " module Foo where"
230210 , " import Data.Maybe"
@@ -235,13 +215,3 @@ spec = do
235215 , " import Yabar"
236216 , " one = two"
237217 ]
238-
239- {-
240- src/Command.hs:263:106: error: [GHC-88464]
241- Data constructor not in scope: PascalCase :: [String] -> String
242- Suggested fix: Perhaps use variable `pascalCase' (line 366)
243-
244- test/Language/Haskell/GhciWrapperSpec.hs:164:25: error: [GHC-88464]
245- Data constructor not in scope:
246- NotInScope :: t0 -> [a0] -> GHC.Diagnostic.Annotated.Annotation
247- -}
0 commit comments