Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
cabal-dev
dist
dist-*
test/data/AST/
node_modules/
*.o
*.hi
Expand Down
50 changes: 46 additions & 4 deletions agda-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,20 @@ library
exposed-modules:
Agda
Agda.Convert
Agda.Interaction.Imports.More
Agda.Interaction.Imports.Virtual
Agda.Interaction.Library.More
Agda.IR
Agda.Parser
Agda.Position
Agda.Syntax.Abstract.More
Control.Concurrent.SizedChan
Indexer
Indexer.Indexer
Indexer.Monad
Indexer.Postprocess
Language.LSP.Protocol.Types.More
Language.LSP.Protocol.Types.Uri.More
Monad
Options
Render
Expand All @@ -70,6 +80,14 @@ library
Server
Server.CommandController
Server.Handler
Server.Handler.TextDocument.DocumentSymbol
Server.Handler.TextDocument.FileManagement
Server.Model
Server.Model.AgdaFile
Server.Model.AgdaLib
Server.Model.Handler
Server.Model.Monad
Server.Model.Symbol
Server.ResponseController
Switchboard
other-modules:
Expand Down Expand Up @@ -160,23 +178,40 @@ executable als
if arch(wasm32)
build-depends:
unix >=2.8.0.0 && <2.9
ghc-options: -with-rtsopts=-V1
else
if !arch(wasm32)
ghc-options: -threaded -with-rtsopts=-N

test-suite als-test
type: exitcode-stdio-1.0
main-is: Test.hs
other-modules:
Test.Indexer.Invariants
Test.Indexer.NoAnonFunSymbol
Test.Indexer.NoDuplicateDecl
Test.Indexer.NoMissing
Test.Indexer.NoOverlap
Test.LSP
Test.Model
Test.ModelMonad
Test.SrcLoc
Test.WASM
TestData
Agda
Agda.Convert
Agda.Interaction.Imports.More
Agda.Interaction.Imports.Virtual
Agda.Interaction.Library.More
Agda.IR
Agda.Parser
Agda.Position
Agda.Syntax.Abstract.More
Control.Concurrent.SizedChan
Indexer
Indexer.Indexer
Indexer.Monad
Indexer.Postprocess
Language.LSP.Protocol.Types.More
Language.LSP.Protocol.Types.Uri.More
Monad
Options
Render
Expand All @@ -194,6 +229,14 @@ test-suite als-test
Server
Server.CommandController
Server.Handler
Server.Handler.TextDocument.DocumentSymbol
Server.Handler.TextDocument.FileManagement
Server.Model
Server.Model.AgdaFile
Server.Model.AgdaLib
Server.Model.Handler
Server.Model.Monad
Server.Model.Symbol
Server.ResponseController
Switchboard
Paths_agda_language_server
Expand Down Expand Up @@ -242,6 +285,5 @@ test-suite als-test
if arch(wasm32)
build-depends:
unix >=2.8.0.0 && <2.9
ghc-options: -with-rtsopts=-V1
else
if !arch(wasm32)
ghc-options: -threaded -with-rtsopts=-N
14 changes: 7 additions & 7 deletions src/Agda.hs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ import Agda.Interaction.JSONTop ()
getAgdaVersion :: String
getAgdaVersion = versionWithCommitInfo

start :: ServerM IO ()
start :: ServerT IO ()
start = do
env <- ask

Expand Down Expand Up @@ -136,7 +136,7 @@ start = do
Left _err -> return ()
Right _val -> return ()
where
loop :: Env -> ServerM CommandM ()
loop :: Env -> ServerT CommandM ()
loop env = do
Bench.reset
done <- Bench.billTo [] $ do
Expand All @@ -163,7 +163,7 @@ start = do

-- | Convert "CommandReq" to "CommandRes"

sendCommand :: MonadIO m => Value -> ServerM m Value
sendCommand :: MonadIO m => Value -> ServerT m Value
sendCommand value = do
-- JSON Value => Request => Response
case fromJSON value of
Expand All @@ -179,7 +179,7 @@ sendCommand value = do
JSON.Success request -> toJSON <$> handleCommandReq request


handleCommandReq :: MonadIO m => CommandReq -> ServerM m CommandRes
handleCommandReq :: MonadIO m => CommandReq -> ServerT m CommandRes
handleCommandReq CmdReqSYN = return $ CmdResACK Agda.getAgdaVersion versionNumber
handleCommandReq (CmdReq cmd) = do
case parseIOTCM cmd of
Expand All @@ -194,7 +194,7 @@ handleCommandReq (CmdReq cmd) = do
--------------------------------------------------------------------------------

getCommandLineOptions
:: (HasOptions m, MonadIO m) => ServerM m CommandLineOptions
:: (HasOptions m, MonadIO m) => ServerT m CommandLineOptions
getCommandLineOptions = do
-- command line options from ARGV
argv <- asks (optRawAgdaOptions . envOptions)
Expand All @@ -215,10 +215,10 @@ getCommandLineOptions = do

-- | Run a TCM action in IO and throw away all of the errors
-- TODO: handle the caught errors
runAgda :: MonadIO m => ServerM TCM a -> ServerM m (Either String a)
runAgda :: MonadIO m => ServerT TCM a -> ServerT m (Either String a)
runAgda p = do
env <- ask
let p' = runServerM env p
let p' = runServerT env p
liftIO
$ runTCMTop'
( (Right <$> p')
Expand Down
195 changes: 195 additions & 0 deletions src/Agda/Interaction/Imports/More.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
{-# LANGUAGE CPP #-}

module Agda.Interaction.Imports.More
( setOptionsFromSourcePragmas,
checkModuleName',
runPMDropWarnings,
moduleName,
runPM,
beginningOfFile,
)
where

import Agda.Interaction.FindFile (
SourceFile (SourceFile),
checkModuleName,
#if MIN_VERSION_Agda(2,8,0)
rootNameModule,
#else
moduleName,
#endif
)
import Agda.Interaction.Imports (Source (..))
import qualified Agda.Interaction.Imports as Imp
import Agda.Interaction.Library (OptionsPragma (..), _libPragmas)
import Agda.Syntax.Common (TopLevelModuleName')
import qualified Agda.Syntax.Concrete as C
import Agda.Syntax.Parser (
moduleParser,
parseFile,
#if MIN_VERSION_Agda(2,8,0)
parse,
moduleNameParser,
#else
PM,
runPMIO,
#endif
)
import Agda.Syntax.Position
( Range,
Range' (Range),
RangeFile,
getRange,
intervalToRange,
mkRangeFile,
posToRange,
posToRange',
startPos,
#if MIN_VERSION_Agda(2,8,0)
beginningOfFile,
rangeFromAbsolutePath,
#endif
)
import Agda.Syntax.TopLevelModuleName (
TopLevelModuleName,
RawTopLevelModuleName (..),
#if MIN_VERSION_Agda(2,8,0)
rawTopLevelModuleNameForModule,
#endif
)
import Agda.TypeChecking.Monad
( Interface,
TCM,
checkAndSetOptionsFromPragma,

Check failure on line 63 in src/Agda/Interaction/Imports/More.hs

View workflow job for this annotation

GitHub Actions / Build and Test (macos-latest, Agda-2.6.4.3)

Module ‘Agda.TypeChecking.Monad’ does not export ‘checkAndSetOptionsFromPragma’.

Check failure on line 63 in src/Agda/Interaction/Imports/More.hs

View workflow job for this annotation

GitHub Actions / Build and Test (macos-13, Agda-2.6.4.3)

Module ‘Agda.TypeChecking.Monad’ does not export ‘checkAndSetOptionsFromPragma’.
setCurrentRange,
setOptionsFromPragma,
setTCLens,
stPragmaOptions,
useTC,
#if MIN_VERSION_Agda(2,8,0)
runPM,
runPMDropWarnings,
#endif
)
import qualified Agda.TypeChecking.Monad as TCM
import qualified Agda.TypeChecking.Monad.Benchmark as Bench
#if MIN_VERSION_Agda(2,8,0)
#else
import Agda.TypeChecking.Warnings (runPM)
#endif
import Agda.Utils.FileName (AbsolutePath)
import Agda.Utils.Monad (bracket_)
#if MIN_VERSION_Agda(2,8,0)
import qualified Data.Text as T
#endif
import qualified Data.Text.Lazy as TL
import Control.Monad.Error.Class (
#if MIN_VERSION_Agda(2,8,0)
catchError,
#else
throwError,
#endif
)
#if MIN_VERSION_Agda(2,8,0)
import Agda.Utils.Singleton (singleton)
#else
import Agda.Syntax.Common.Pretty (pretty)
#endif

srcFilePath :: SourceFile -> TCM AbsolutePath
#if MIN_VERSION_Agda(2,8,0)
srcFilePath = TCM.srcFilePath
#else
srcFilePath (SourceFile f) = return f
#endif

#if MIN_VERSION_Agda(2,8,0)
-- beginningOfFile was generalized in Agda 2.8.0 to support the features we
-- need, so we just import it
#else
beginningOfFile :: RangeFile -> Range
beginningOfFile rf = posToRange (startPos $ Just rf) (startPos $ Just rf)
#endif

#if MIN_VERSION_Agda(2,8,0)
-- runPMDropWarnings was introduced in Agda 2.8.0, so we just import it
#else
runPMDropWarnings :: PM a -> TCM a
runPMDropWarnings m = do
(res, _ws) <- runPMIO m
case res of
Left e -> throwError $ TCM.Exception (getRange e) (pretty e)
Right a -> return a
#endif

-- Unexported Agda functions

srcDefaultPragmas :: Imp.Source -> [OptionsPragma]
srcDefaultPragmas src = map _libPragmas (Imp.srcProjectLibs src)

srcFilePragmas :: Imp.Source -> [OptionsPragma]
srcFilePragmas src = pragmas
where
cpragmas = C.modPragmas (Imp.srcModule src)
pragmas =
[ OptionsPragma
{ pragmaStrings = opts,
pragmaRange = r
}
| C.OptionsPragma r opts <- cpragmas
]

-- | Set options from a 'Source' pragma, using the source
-- ranges of the pragmas for error reporting. Flag to check consistency.
setOptionsFromSourcePragmas :: Bool -> Imp.Source -> TCM ()
setOptionsFromSourcePragmas checkOpts src = do
mapM_ setOpts (srcDefaultPragmas src)
mapM_ setOpts (srcFilePragmas src)
where
setOpts
| checkOpts = checkAndSetOptionsFromPragma
| otherwise = setOptionsFromPragma

-- Andreas, 2016-07-11, issue 2092
-- The error range should be set to the file with the wrong module name
-- not the importing one (which would be the default).
checkModuleName' :: TopLevelModuleName' Range -> SourceFile -> TCM ()
checkModuleName' m f =
setCurrentRange m $ checkModuleName m f Nothing

#if MIN_VERSION_Agda(2,8,0)
-- moduleName was exported until 2.8.0

-- | Computes the module name of the top-level module in the given file.
--
-- If no top-level module name is given, then an attempt is made to
-- use the file name as a module name.

moduleName ::
AbsolutePath
-- ^ The path to the file.
-> C.Module
-- ^ The parsed module.
-> TCM TopLevelModuleName
moduleName file parsedModule = Bench.billTo [Bench.ModuleName] $ do
let defaultName = rootNameModule file
raw = rawTopLevelModuleNameForModule parsedModule
TCM.topLevelModuleName =<< if C.isNoName raw
then setCurrentRange (rangeFromAbsolutePath file) $ do
m <- runPM (fst <$> parse moduleNameParser defaultName)
`catchError` \_ ->
TCM.typeError $ TCM.InvalidFileName file TCM.DoesNotCorrespondToValidModuleName
case m of
C.Qual{} ->
TCM.typeError $ TCM.InvalidFileName file $
TCM.RootNameModuleNotAQualifiedModuleName $ T.pack defaultName
C.QName{} ->
return $ RawTopLevelModuleName
{ rawModuleNameRange = getRange m
, rawModuleNameParts = singleton (T.pack defaultName)
, rawModuleNameInferred = True
-- Andreas, 2025-06-21, issue #7953:
-- Remember we made up this module name to improve errors.
}
else return raw
#endif
Loading
Loading