summaryrefslogtreecommitdiff
path: root/tests/Language/PureScript/Ide/SourceFileSpec.hs
blob: 1bf01f470a7b2497bc3e5387bb8772125e8b0be8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Language.PureScript.Ide.SourceFileSpec where

import           Protolude

import qualified Language.PureScript as P
import           Language.PureScript.Ide.Command
import           Language.PureScript.Ide.SourceFile
import           Language.PureScript.Ide.Types
import           Language.PureScript.Ide.Test
import           Test.Hspec

span0, span1, span2 :: P.SourceSpan
span0 = P.SourceSpan "ModuleLevel" (P.SourcePos 0 0) (P.SourcePos 1 1)
span1 = P.SourceSpan "" (P.SourcePos 1 1) (P.SourcePos 2 2)
span2 = P.SourceSpan "" (P.SourcePos 2 2) (P.SourcePos 3 3)

ann0, ann1, ann2 :: P.SourceAnn
ann0 = (span0, [])
ann1 = (span1, [])
ann2 = (span2, [])

typeAnnotation1, value1, synonym1, class1, class2, data1, data2, valueFixity, typeFixity, foreign1, foreign2, foreign3, member1 :: P.Declaration
typeAnnotation1 = P.TypeDeclaration ann1 (P.Ident "value1") P.REmpty
value1 = P.ValueDeclaration ann1 (P.Ident "value1") P.Public [] []
synonym1 = P.TypeSynonymDeclaration ann1 (P.ProperName "Synonym1") [] P.REmpty
class1 = P.TypeClassDeclaration ann1 (P.ProperName "Class1") [] [] [] []
class2 = P.TypeClassDeclaration ann1 (P.ProperName "Class2") [] [] [] [member1]
data1 = P.DataDeclaration ann1 P.Newtype (P.ProperName "Data1") [] []
data2 = P.DataDeclaration ann1 P.Data (P.ProperName "Data2") [] [(P.ProperName "Cons1", [])]
valueFixity =
  P.ValueFixityDeclaration
    ann1
    (P.Fixity P.Infix 0)
    (P.Qualified Nothing (Left (P.Ident "")))
    (P.OpName "<$>")
typeFixity =
  P.TypeFixityDeclaration
    ann1
    (P.Fixity P.Infix 0)
    (P.Qualified Nothing (P.ProperName ""))
    (P.OpName "~>")
foreign1 = P.ExternDeclaration ann1 (P.Ident "foreign1") P.REmpty
foreign2 = P.ExternDataDeclaration ann1 (P.ProperName "Foreign2") P.kindType
foreign3 = P.ExternKindDeclaration ann1 (P.ProperName "Foreign3")
member1 = P.TypeDeclaration ann2 (P.Ident "member1") P.REmpty

spec :: Spec
spec = do
  describe "Extracting Spans" $ do
    it "extracts a span for a value declaration" $
      extractSpans value1 `shouldBe` [(IdeNamespaced IdeNSValue "value1", span1)]
    it "extracts a span for a type synonym declaration" $
      extractSpans synonym1 `shouldBe` [(IdeNamespaced IdeNSType "Synonym1", span1)]
    it "extracts a span for a typeclass declaration" $
      extractSpans class1 `shouldBe` [(IdeNamespaced IdeNSType "Class1", span1)]
    it "extracts spans for a typeclass declaration and its members" $
      extractSpans class2 `shouldBe` [(IdeNamespaced IdeNSType "Class2", span1), (IdeNamespaced IdeNSValue "member1", span2)]
    it "extracts a span for a data declaration" $
      extractSpans data1 `shouldBe` [(IdeNamespaced IdeNSType "Data1", span1)]
    it "extracts spans for a data declaration and its constructors" $
      extractSpans data2 `shouldBe` [(IdeNamespaced IdeNSType "Data2", span1), (IdeNamespaced IdeNSValue "Cons1", span1)]
    it "extracts a span for a value operator fixity declaration" $
      extractSpans valueFixity `shouldBe` [(IdeNamespaced IdeNSValue "<$>", span1)]
    it "extracts a span for a type operator fixity declaration" $
      extractSpans typeFixity `shouldBe` [(IdeNamespaced IdeNSType "~>", span1)]
    it "extracts a span for a foreign declaration" $
      extractSpans foreign1 `shouldBe` [(IdeNamespaced IdeNSValue "foreign1", span1)]
    it "extracts a span for a data foreign declaration" $
      extractSpans foreign2 `shouldBe` [(IdeNamespaced IdeNSType "Foreign2", span1)]
    it "extracts a span for a foreign kind declaration" $
      extractSpans foreign3 `shouldBe` [(IdeNamespaced IdeNSKind "Foreign3", span1)]
  describe "Type annotations" $ do
    it "extracts a type annotation" $
      extractTypeAnnotations [typeAnnotation1] `shouldBe` [(P.Ident "value1", P.REmpty)]
  describe "Finding Source Spans for identifiers" $ do
    it "finds a value declaration" $ do
      Just r <- getLocation "sfValue"
      r `shouldBe` valueSS
    it "finds a synonym declaration" $ do
      Just r <- getLocation "SFType"
      r `shouldBe` synonymSS
    it "finds a data declaration and its constructors" $ do
      rs <- traverse getLocation ["SFData", "SFOne", "SFTwo", "SFThree"]
      traverse_ (`shouldBe` (Just typeSS)) rs
    it "finds a class declaration" $ do
      Just r <- getLocation "SFClass"
      r `shouldBe` classSS
    it "finds a value operator declaration" $ do
      Just r <- getLocation "<$>"
      r `shouldBe` valueOpSS
    it "finds a type operator declaration" $ do
      Just r <- getLocation "~>"
      r `shouldBe` typeOpSS

getLocation :: Text -> IO (Maybe P.SourceSpan)
getLocation s = do
  ([Right (CompletionResult [c])], _) <-
    runIde' defConfig ideState [Type s [] Nothing]
  pure (complLocation c)
  where
    ideState = emptyIdeState `volatileState`
      [ ("Test",
         [ ideValue "sfValue" Nothing `annLoc` valueSS
         , ideSynonym "SFType" Nothing Nothing `annLoc` synonymSS
         , ideType "SFData" Nothing [] `annLoc` typeSS
         , ideDtor "SFOne" "SFData" Nothing `annLoc` typeSS
         , ideDtor "SFTwo" "SFData" Nothing `annLoc` typeSS
         , ideDtor "SFThree" "SFData" Nothing `annLoc` typeSS
         , ideTypeClass "SFClass" P.kindType [] `annLoc` classSS
         , ideValueOp "<$>" (P.Qualified Nothing (Left "")) 0 Nothing Nothing
           `annLoc` valueOpSS
         , ideTypeOp "~>" (P.Qualified Nothing "") 0 Nothing Nothing
           `annLoc` typeOpSS
         ])
      ]