forked from purescript/purescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExterns.hs
More file actions
152 lines (136 loc) · 5.99 KB
/
Externs.hs
File metadata and controls
152 lines (136 loc) · 5.99 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
-----------------------------------------------------------------------------
--
-- Module : Language.PureScript.Ide.Externs
-- Description : Handles externs files for psc-ide
-- Copyright : Christoph Hegemann 2016
-- License : MIT (http://opensource.org/licenses/MIT)
--
-- Maintainer : Christoph Hegemann <christoph.hegemann1337@gmail.com>
-- Stability : experimental
--
-- |
-- Handles externs files for psc-ide
-----------------------------------------------------------------------------
{-# LANGUAGE PackageImports #-}
module Language.PureScript.Ide.Externs
( readExternFile
, convertExterns
, annotateModule
) where
import Protolude
import Control.Lens ((^.))
import "monad-logger" Control.Monad.Logger
import Data.Aeson (decodeStrict)
import qualified Data.ByteString as BS
import qualified Data.Map as Map
import Data.Version (showVersion)
import Language.PureScript.Ide.Error (IdeError (..))
import Language.PureScript.Ide.Types
import Language.PureScript.Ide.Util
import qualified Language.PureScript as P
readExternFile :: (MonadIO m, MonadError IdeError m, MonadLogger m) =>
FilePath -> m P.ExternsFile
readExternFile fp = do
parseResult <- liftIO (decodeStrict <$> BS.readFile fp)
case parseResult of
Nothing ->
throwError (GeneralError
("Parsing the extern at: " <> toS fp <> " failed"))
Just externs
| P.efVersion externs /= version -> do
let errMsg = "Version mismatch for the externs at: " <> toS fp
<> " Expected: " <> version
<> " Found: " <> P.efVersion externs
logErrorN errMsg
throwError (GeneralError errMsg)
Just externs -> pure externs
where
version = toS (showVersion P.version)
convertExterns :: P.ExternsFile -> ([IdeDeclarationAnn], [(P.ModuleName, P.DeclarationRef)])
convertExterns ef =
(decls, exportDecls)
where
decls = map
(IdeDeclarationAnn emptyAnn)
(cleanDeclarations ++ operatorDecls ++ tyOperatorDecls)
exportDecls = mapMaybe (convertExport . unwrapPositionedRef) (P.efExports ef)
operatorDecls = convertOperator <$> P.efFixities ef
tyOperatorDecls = convertTypeOperator <$> P.efTypeFixities ef
declarations = mapMaybe convertDecl (P.efDeclarations ef)
typeClassFilter = foldMap removeTypeDeclarationsForClass (filter isTypeClassDeclaration declarations)
cleanDeclarations = ordNub (appEndo typeClassFilter declarations)
removeTypeDeclarationsForClass :: IdeDeclaration -> Endo [IdeDeclaration]
removeTypeDeclarationsForClass (IdeDeclTypeClass n) = Endo (filter notDuplicate)
where notDuplicate (IdeDeclType t) =
n ^. ideTCName . properNameT /= t ^. ideTypeName . properNameT
notDuplicate (IdeDeclTypeSynonym s) =
n ^. ideTCName . properNameT /= s ^. ideSynonymName . properNameT
notDuplicate _ = True
removeTypeDeclarationsForClass _ = mempty
isTypeClassDeclaration :: IdeDeclaration -> Bool
isTypeClassDeclaration IdeDeclTypeClass{} = True
isTypeClassDeclaration _ = False
convertExport :: P.DeclarationRef -> Maybe (P.ModuleName, P.DeclarationRef)
convertExport (P.ReExportRef m r) = Just (m, r)
convertExport _ = Nothing
convertDecl :: P.ExternsDeclaration -> Maybe IdeDeclaration
convertDecl P.EDType{..} = Just $ IdeDeclType $
IdeType edTypeName edTypeKind
convertDecl P.EDTypeSynonym{..} = Just $ IdeDeclTypeSynonym
(IdeTypeSynonym edTypeSynonymName edTypeSynonymType)
convertDecl P.EDDataConstructor{..} = Just $ IdeDeclDataConstructor $
IdeDataConstructor edDataCtorName edDataCtorTypeCtor edDataCtorType
convertDecl P.EDValue{..} = Just $ IdeDeclValue $
IdeValue edValueName edValueType
convertDecl P.EDClass{..} = Just $ IdeDeclTypeClass $
IdeTypeClass edClassName []
convertDecl P.EDKind{..} = Just (IdeDeclKind edKindName)
convertDecl P.EDInstance{} = Nothing
convertOperator :: P.ExternsFixity -> IdeDeclaration
convertOperator P.ExternsFixity{..} =
IdeDeclValueOperator $ IdeValueOperator
efOperator
efAlias
efPrecedence
efAssociativity
Nothing
convertTypeOperator :: P.ExternsTypeFixity -> IdeDeclaration
convertTypeOperator P.ExternsTypeFixity{..} =
IdeDeclTypeOperator $ IdeTypeOperator
efTypeOperator
efTypeAlias
efTypePrecedence
efTypeAssociativity
Nothing
annotateModule
:: (DefinitionSites P.SourceSpan, TypeAnnotations)
-> [IdeDeclarationAnn]
-> [IdeDeclarationAnn]
annotateModule (defs, types) decls =
map convertDeclaration decls
where
convertDeclaration :: IdeDeclarationAnn -> IdeDeclarationAnn
convertDeclaration (IdeDeclarationAnn ann d) = case d of
IdeDeclValue v ->
annotateFunction (v ^. ideValueIdent) (IdeDeclValue v)
IdeDeclType t ->
annotateType (t ^. ideTypeName . properNameT) (IdeDeclType t)
IdeDeclTypeSynonym s ->
annotateType (s ^. ideSynonymName . properNameT) (IdeDeclTypeSynonym s)
IdeDeclDataConstructor dtor ->
annotateValue (dtor ^. ideDtorName . properNameT) (IdeDeclDataConstructor dtor)
IdeDeclTypeClass tc ->
annotateType (tc ^. ideTCName . properNameT) (IdeDeclTypeClass tc)
IdeDeclValueOperator op ->
annotateValue (op ^. ideValueOpName . opNameT) (IdeDeclValueOperator op)
IdeDeclTypeOperator op ->
annotateType (op ^. ideTypeOpName . opNameT) (IdeDeclTypeOperator op)
IdeDeclKind i ->
annotateKind (i ^. properNameT) (IdeDeclKind i)
where
annotateFunction x = IdeDeclarationAnn (ann { annLocation = Map.lookup (IdeNSValue (P.runIdent x)) defs
, annTypeAnnotation = Map.lookup x types
})
annotateValue x = IdeDeclarationAnn (ann {annLocation = Map.lookup (IdeNSValue x) defs})
annotateType x = IdeDeclarationAnn (ann {annLocation = Map.lookup (IdeNSType x) defs})
annotateKind x = IdeDeclarationAnn (ann {annLocation = Map.lookup (IdeNSKind x) defs})