{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE TemplateHaskell #-}
module Language.PureScript.Ide.Types where
import Protolude hiding (moduleName)
import Control.Concurrent.STM
import Control.Lens.TH
import Data.Aeson
import qualified Data.Map.Lazy as M
import qualified Language.PureScript as P
import qualified Language.PureScript.Errors.JSON as P
type ModuleIdent = Text
type ModuleMap a = Map P.ModuleName a
data IdeDeclaration
= IdeDeclValue IdeValue
| IdeDeclType IdeType
| IdeDeclTypeSynonym IdeTypeSynonym
| IdeDeclDataConstructor IdeDataConstructor
| IdeDeclTypeClass IdeTypeClass
| IdeDeclValueOperator IdeValueOperator
| IdeDeclTypeOperator IdeTypeOperator
| IdeDeclKind (P.ProperName 'P.KindName)
deriving (Show, Eq, Ord, Generic, NFData)
data IdeValue = IdeValue
{ _ideValueIdent :: P.Ident
, _ideValueType :: P.Type
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeType = IdeType
{ _ideTypeName :: P.ProperName 'P.TypeName
, _ideTypeKind :: P.Kind
, _ideTypeDtors :: [(P.ProperName 'P.ConstructorName, P.Type)]
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeTypeSynonym = IdeTypeSynonym
{ _ideSynonymName :: P.ProperName 'P.TypeName
, _ideSynonymType :: P.Type
, _ideSynonymKind :: P.Kind
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeDataConstructor = IdeDataConstructor
{ _ideDtorName :: P.ProperName 'P.ConstructorName
, _ideDtorTypeName :: P.ProperName 'P.TypeName
, _ideDtorType :: P.Type
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeTypeClass = IdeTypeClass
{ _ideTCName :: P.ProperName 'P.ClassName
, _ideTCKind :: P.Kind
, _ideTCInstances :: [IdeInstance]
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeInstance = IdeInstance
{ _ideInstanceModule :: P.ModuleName
, _ideInstanceName :: P.Ident
, _ideInstanceTypes :: [P.Type]
, _ideInstanceConstraints :: Maybe [P.Constraint]
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeValueOperator = IdeValueOperator
{ _ideValueOpName :: P.OpName 'P.ValueOpName
, _ideValueOpAlias :: P.Qualified (Either P.Ident (P.ProperName 'P.ConstructorName))
, _ideValueOpPrecedence :: P.Precedence
, _ideValueOpAssociativity :: P.Associativity
, _ideValueOpType :: Maybe P.Type
} deriving (Show, Eq, Ord, Generic, NFData)
data IdeTypeOperator = IdeTypeOperator
{ _ideTypeOpName :: P.OpName 'P.TypeOpName
, _ideTypeOpAlias :: P.Qualified (P.ProperName 'P.TypeName)
, _ideTypeOpPrecedence :: P.Precedence
, _ideTypeOpAssociativity :: P.Associativity
, _ideTypeOpKind :: Maybe P.Kind
} deriving (Show, Eq, Ord, Generic, NFData)
makePrisms ''IdeDeclaration
makeLenses ''IdeValue
makeLenses ''IdeType
makeLenses ''IdeTypeSynonym
makeLenses ''IdeDataConstructor
makeLenses ''IdeTypeClass
makeLenses ''IdeInstance
makeLenses ''IdeValueOperator
makeLenses ''IdeTypeOperator
data IdeDeclarationAnn = IdeDeclarationAnn
{ _idaAnnotation :: Annotation
, _idaDeclaration :: IdeDeclaration
} deriving (Show, Eq, Ord, Generic, NFData)
data Annotation
= Annotation
{ _annLocation :: Maybe P.SourceSpan
, _annExportedFrom :: Maybe P.ModuleName
, _annTypeAnnotation :: Maybe P.Type
, _annDocumentation :: Maybe Text
} deriving (Show, Eq, Ord, Generic, NFData)
makeLenses ''Annotation
makeLenses ''IdeDeclarationAnn
emptyAnn :: Annotation
emptyAnn = Annotation Nothing Nothing Nothing Nothing
type DefinitionSites a = Map IdeNamespaced a
type TypeAnnotations = Map P.Ident P.Type
newtype AstData a = AstData (ModuleMap (DefinitionSites a, TypeAnnotations))
deriving (Show, Eq, Ord, Generic, NFData, Functor, Foldable)
data IdeLogLevel = LogDebug | LogPerf | LogAll | LogDefault | LogNone
deriving (Show, Eq)
data IdeConfiguration =
IdeConfiguration
{ confOutputPath :: FilePath
, confLogLevel :: IdeLogLevel
, confGlobs :: [FilePath]
, confEditorMode :: Bool
}
data IdeEnvironment =
IdeEnvironment
{ ideStateVar :: TVar IdeState
, ideConfiguration :: IdeConfiguration
}
type Ide m = (MonadIO m, MonadReader IdeEnvironment m)
data IdeState = IdeState
{ ideFileState :: IdeFileState
, ideVolatileState :: IdeVolatileState
} deriving (Show)
emptyIdeState :: IdeState
emptyIdeState = IdeState emptyFileState emptyVolatileState
emptyFileState :: IdeFileState
emptyFileState = IdeFileState M.empty M.empty
emptyVolatileState :: IdeVolatileState
emptyVolatileState = IdeVolatileState (AstData M.empty) M.empty Nothing
data IdeFileState = IdeFileState
{ fsExterns :: ModuleMap P.ExternsFile
, fsModules :: ModuleMap (P.Module, FilePath)
} deriving (Show)
data IdeVolatileState = IdeVolatileState
{ vsAstData :: AstData P.SourceSpan
, vsDeclarations :: ModuleMap [IdeDeclarationAnn]
, vsCachedRebuild :: Maybe (P.ModuleName, P.ExternsFile)
} deriving (Show)
newtype Match a = Match (P.ModuleName, a)
deriving (Show, Eq, Functor)
data Completion = Completion
{ complModule :: Text
, complIdentifier :: Text
, complType :: Text
, complExpandedType :: Text
, complLocation :: Maybe P.SourceSpan
, complDocumentation :: Maybe Text
, complExportedFrom :: [P.ModuleName]
} deriving (Show, Eq, Ord)
instance ToJSON Completion where
toJSON (Completion {..}) =
object [ "module" .= complModule
, "identifier" .= complIdentifier
, "type" .= complType
, "expandedType" .= complExpandedType
, "definedAt" .= complLocation
, "documentation" .= complDocumentation
, "exportedFrom" .= map P.runModuleName complExportedFrom
]
identifierFromDeclarationRef :: P.DeclarationRef -> Text
identifierFromDeclarationRef (P.TypeRef _ name _) = P.runProperName name
identifierFromDeclarationRef (P.ValueRef _ ident) = P.runIdent ident
identifierFromDeclarationRef (P.TypeClassRef _ name) = P.runProperName name
identifierFromDeclarationRef (P.KindRef _ name) = P.runProperName name
identifierFromDeclarationRef (P.ValueOpRef _ op) = P.showOp op
identifierFromDeclarationRef (P.TypeOpRef _ op) = P.showOp op
identifierFromDeclarationRef _ = ""
data Success =
CompletionResult [Completion]
| TextResult Text
| UsagesResult [P.SourceSpan]
| MultilineTextResult [Text]
| ImportList (P.ModuleName, [(P.ModuleName, P.ImportDeclarationType, Maybe P.ModuleName)])
| ModuleList [ModuleIdent]
| RebuildSuccess P.MultipleErrors
deriving (Show)
encodeSuccess :: (ToJSON a) => a -> Value
encodeSuccess res =
object ["resultType" .= ("success" :: Text), "result" .= res]
instance ToJSON Success where
toJSON (CompletionResult cs) = encodeSuccess cs
toJSON (TextResult t) = encodeSuccess t
toJSON (UsagesResult ssp) = encodeSuccess ssp
toJSON (MultilineTextResult ts) = encodeSuccess ts
toJSON (ImportList (moduleName, imports)) = object [ "resultType" .= ("success" :: Text)
, "result" .= object [ "imports" .= map encodeImport imports
, "moduleName" .= P.runModuleName moduleName]]
toJSON (ModuleList modules) = encodeSuccess modules
toJSON (RebuildSuccess warnings) = encodeSuccess (P.toJSONErrors False P.Warning warnings)
encodeImport :: (P.ModuleName, P.ImportDeclarationType, Maybe P.ModuleName) -> Value
encodeImport (P.runModuleName -> mn, importType, map P.runModuleName -> qualifier) = case importType of
P.Implicit ->
object $ [ "module" .= mn
, "importType" .= ("implicit" :: Text)
] ++ map (\x -> "qualifier" .= x) (maybeToList qualifier)
P.Explicit refs ->
object $ [ "module" .= mn
, "importType" .= ("explicit" :: Text)
, "identifiers" .= (identifierFromDeclarationRef <$> refs)
] ++ map (\x -> "qualifier" .= x) (maybeToList qualifier)
P.Hiding refs ->
object $ [ "module" .= mn
, "importType" .= ("hiding" :: Text)
, "identifiers" .= (identifierFromDeclarationRef <$> refs)
] ++ map (\x -> "qualifier" .= x) (maybeToList qualifier)
data IdeNamespace = IdeNSValue | IdeNSType | IdeNSKind
deriving (Show, Eq, Ord, Generic, NFData)
instance FromJSON IdeNamespace where
parseJSON (String s) = case s of
"value" -> pure IdeNSValue
"type" -> pure IdeNSType
"kind" -> pure IdeNSKind
_ -> mzero
parseJSON _ = mzero
data IdeNamespaced = IdeNamespaced IdeNamespace Text
deriving (Show, Eq, Ord, Generic, NFData)