@@ -17,6 +17,7 @@ import Data.OneOf
1717import Data.SortedMap
1818import Data.SortedSet
1919import Data.String
20+ import Idris.CommandLine
2021import Idris.Doc.String
2122import Idris.Error
2223import Idris.IDEMode.Holes
@@ -176,15 +177,28 @@ processSettings (JObject xs) = do
176177 when (pp. showMachineNames /= b) $ do
177178 setPPrint ({ showMachineNames : = b } pp)
178179 update LSPConf ({ cachedHovers : = empty })
180+ logI Configuration " Show machine names set to \{show b}"
179181 Just _ => logE Configuration " Incorrect type for show machine names, expected boolean"
180182 Nothing => pure ()
181183 case lookup " logSeverity" xs of
182184 Just (JString ll) =>
183- whenJust (parseSeverity ll) $ \ l => update LSPConf ({ logSeverity : = l})
185+ case parseSeverity ll of
186+ Just l => update LSPConf ({ logSeverity : = l}) >> logI Configuration "Log severity set to \{show l}"
187+ Nothing => logE Configuration " Incorrect string for log severity"
184188 Just _ => logE Configuration " Incorrect type for log severity, expected string"
185189 Nothing => pure ()
186190 case lookup " briefCompletions" xs of
187- Just (JBoolean b) => update LSPConf ({ briefCompletions : = b})
191+ Just (JBoolean b) => do
192+ update LSPConf ({ briefCompletions : = b})
193+ logI Configuration " Brief completions set to \{show b}"
194+ _ => pure ()
195+ case lookup " ipkgPath" xs of
196+ Just (JString path) => do
197+ update LSPConf ({ ipkgPath : = Just path})
198+ logI Channel " Ipkg path set to \{path}"
199+ Just JNull => do
200+ update LSPConf ({ ipkgPath : = Nothing})
201+ logI Channel " Ipkg path unset"
188202 _ => pure ()
189203processSettings _ = logE Configuration " Incorrect type for options"
190204
@@ -200,83 +214,91 @@ loadURI : Ref LSPConf LSPConfiguration
200214 => Ref Syn SyntaxInfo
201215 => Ref MD Metadata
202216 => Ref ROpts REPLOpts
203- => InitializeParams -> URI -> Maybe Int -> Core (Either String () )
217+ => InitializeParams -> URI -> Maybe Int -> Core (Either () () )
204218loadURI conf uri version = do
205- logI Server " Loading file \{show uri}"
219+ logI Channel " Loading file \{show uri}"
206220 defs <- get Ctxt
207221 let extraDirs = defs. options. dirs. extra_dirs
208- update LSPConf ({ openFile : = Just (uri, fromMaybe 0 version) })
209222 update ROpts { evalResultName : = Nothing }
210223 resetContext (Virtual Interactive )
211224 let fpath = uriPathToSystemPath uri. path
212- let Just (startFolder, startFile) = splitParent fpath
213- | Nothing => do let msg = " Cannot find the parent folder for \{show uri}"
214- logE Server msg
215- pure $ Left msg
216- True <- coreLift $ changeDir startFolder
217- | False => do let msg = " Cannot change current directory to \{show startFolder}, folder of \{show startFile}"
218- logE Server msg
219- pure $ Left msg
220- Right fname <- catch (maybe (Left " Cannot find the ipkg file" ) Right <$> findIpkg (Just fpath))
221- (pure . Left . show )
222- | Left err => do let msg = " Cannot load ipkg file for \{show uri}: \{show err}"
223- logE Server msg
224- pure $ Left msg
225- Right res <- coreLift $ File . ReadWrite . readFile fname
226- | Left err => do let msg = " Cannot read file at \{show uri}"
227- logE Server msg
228- pure $ Left msg
229- update LSPConf ({ virtualDocuments $= insert uri (fromMaybe 0 version, res ++ " \n " ) })
230- -- A hack to solve some interesting edge-cases around missing newlines ^^^^^^^
231- setSource res
225+ -- Save CWD
226+ cwd <- getWorkingDir
227+ Right packageFilePath <- catch
228+ (maybe
229+ (Left (InternalError " Cannot find the .ipkg file" ))
230+ Right
231+ <$>
232+ [| gets LSPConf ipkgPath <+> coreLift (findIpkgFile <&> (<&> (\ (dir, name, _ ) => dir </> name))) | ]
233+ )
234+ (pure . Left )
235+ | Left err => do let msg = " Cannot load .ipkg file: \{show err}"
236+ logE Channel msg
237+ pure $ Left ()
238+ logI Channel " .ipkg file configured to: \{packageFilePath}"
239+ Right packageFileSource <- coreLift $ File . ReadWrite . readFile packageFilePath
240+ | Left err => do let msg = " Cannot read .ipkg at \{packageFilePath} with CWD \{!getWorkingDir}"
241+ logE Channel msg
242+ pure $ Left ()
243+ logI Channel " .ipkg file read!"
244+ let Just (packageFileDir, packageFileName) = splitParent packageFilePath
245+ | _ => throw $ InternalError " Tried to split empty string"
246+ let True = isSuffixOf " .ipkg" packageFileName
247+ | _ => do let msg = " Packages must have an '.ipkg' extension: \{packageFilePath}"
248+ logE Channel msg
249+ pure $ Left ()
250+ -- The CWD should be set to that of the .ipkg file
251+ setWorkingDir packageFileDir
252+ -- Using local packageFileName as we are now in the directory containing that file
253+ -- Idris assumes that CWD and the directory of the .ipkg file coincide
254+ pkg <- parsePkgFile True packageFileName
255+ logI Channel " .ipkg file parsed!"
256+ whenJust (builddir pkg) setBuildDir
257+ setOutputDir (outputdir pkg)
258+ logI Channel " Type checking..."
232259 errs <- catch
233- (buildDeps fname)
260+ (do
261+ (duration, errs) <- clock $ check pkg []
262+ logI Channel " Type-checking finished in \{show duration.milliseconds}ms with \{show (length errs)} errors"
263+ pure errs
264+ )
265+ -- FIXME: the compiler sometimes dumps the errors on stdout, requires
266+ -- a compiler change.
234267 (\ err => do
235268 logE Server " Caught error which shouldn't be leaked while loading file: \{show err}"
236269 pure [err])
237- -- FIXME: the compiler always dumps the errors on stdout, requires
238- -- a compiler change.
239- -- NOTE on catch: It seems the compiler sometimes throws errors instead
240- -- of accumulating them in the buildDeps.
241- unless (null errs) $ do
242- update LSPConf ({ errorFiles $= insert uri })
243- -- ModTree 397--308 loads data into context from ttf/ttm if no errors
244- -- In case of error, we reprocess fname to populate metadata and syntax
245- logI Channel " Rebuild \{fname} due to errors"
246- modIdent <- ctxtPathToNS fname
247- let msgPrefix : Doc IdrisAnn = pretty0 ""
248- let buildMsg : Doc IdrisAnn = pretty0 modIdent
249- clearCtxt; addPrimitives
250- put MD (initMetadata (PhysicalIdrSrc modIdent))
251- ignore $ ProcessIdr . process msgPrefix buildMsg fname modIdent
270+
271+ errs <- case null errs of
272+ True => do -- On success, reload the main ttc in a clean context
273+ clearCtxt; addPrimitives
274+ modIdent <- ctxtPathToNS fpath
275+ mainttc <- getTTCFileName fpath " ttc"
276+ log " import" 10 $ " Reloading " ++ show mainttc ++ " from " ++ fpath
277+ catch ([] <$ readAsMain mainttc) $ (\ err => pure [err])
278+ False => pure errs
279+
252280
253281 let caps = (publishDiagnostics <=< textDocument) . capabilities $ conf
254282 update LSPConf ({ quickfixes : = [], cachedActions := empty, cachedHovers := empty })
255283 traverse_ (findQuickfix caps uri) errs
256284 defs <- get Ctxt
257285 session <- getSession
258286 let warnings = if session. warningsAsErrors then [] else reverse (warnings defs)
259- sendDiagnostics caps uri version warnings errs
287+ -- Clear out all previously issued diagnostics
288+ for_ ! (Prelude . toList <$> gets LSPConf errorFiles) sendEmptyDiagnostic
289+ filesWithErrors <- sendDiagnostics caps uri warnings errs
290+ logI Channel " Files containing errors: \{show filesWithErrors}"
291+ update LSPConf { errorFiles : = SortedSet.fromList filesWithErrors }
260292 defs <- get Ctxt
261293 put Ctxt ({ options-> dirs-> extra_dirs : = extraDirs } defs)
262- cNames <- completionNames
294+ (duration, cNames) <- clock completionNames
295+ logI Channel " Populating completion cache took \{show duration.milliseconds}ms"
263296 update LSPConf ({completionCache $= insert uri cNames})
297+ logI Channel " File loaded!"
298+ -- Reset CWD
299+ setWorkingDir cwd
264300 pure $ Right ()
265301
266- loadIfNeeded : Ref LSPConf LSPConfiguration
267- => Ref Ctxt Defs
268- => Ref UST UState
269- => Ref Syn SyntaxInfo
270- => Ref MD Metadata
271- => Ref ROpts REPLOpts
272- => InitializeParams -> URI -> Maybe Int -> Core (Either String () )
273- loadIfNeeded conf uri version = do
274- Just (oldUri, oldVersion) <- gets LSPConf openFile
275- | Nothing => loadURI conf uri version
276- if (oldUri == uri && (isNothing version || (Just oldVersion) == version))
277- then pure $ Right ()
278- else loadURI conf uri version
279-
280302withURI : Ref LSPConf LSPConfiguration
281303 => Ref Ctxt Defs
282304 => Ref UST UState
@@ -285,13 +307,25 @@ withURI : Ref LSPConf LSPConfiguration
285307 => Ref ROpts REPLOpts
286308 => InitializeParams
287309 -> URI -> Maybe Int -> Core (Either ResponseError a) -> Core (Either ResponseError a) -> Core (Either ResponseError a)
288- withURI conf uri version d k = do
289- when ! (isError uri) $ ignore $ logW Server " Trying to load \{show uri} which has errors" >> d
290- case ! (loadIfNeeded conf uri version) of
291- Right () => k
292- Left err => do
293- logE Server " Error while loading \{show uri}: \{show err}"
294- pure $ Left (MkResponseError (Custom 3 ) err JNull )
310+ withURI conf uri version d k =
311+ case ! (isError uri) of
312+ True => logI Server " Trying to load \{show uri} which has errors" >> d
313+ False => do
314+ logI Channel " Loading metadata for file: \{show uri}"
315+ clock0 <- coreLift (clockTime Monotonic )
316+ let fpath = uriPathToSystemPath uri. path
317+ setMainFile (Just fpath)
318+ Right src <- coreLift $ File . ReadWrite . readFile fpath
319+ | Left err => pure $ Left (MkResponseError RequestCancelled " Couldn't read the file source file" JNull )
320+ setSource src
321+ modIdent <- ctxtPathToNS fpath
322+ mainttm <- getTTCFileName fpath " ttm"
323+ [] <- catch ([] <$ readFromTTM mainttm) (\ err => pure [err])
324+ | _ => pure $ Left (MkResponseError RequestCancelled " Couldn't load TTM for the file" JNull )
325+ clock1 <- coreLift (clockTime Monotonic )
326+ let dif = timeDifference clock1 clock0
327+ logI Channel " Loading metadata finished in \{show dif.milliseconds}ms"
328+ k
295329
296330||| Guard for requests that requires a successful initialization before being allowed.
297331whenInitializedRequest : Ref LSPConf LSPConfiguration => (InitializeParams -> Core (Either ResponseError a)) -> Core (Either ResponseError a)
@@ -498,12 +532,19 @@ handleRequest TextDocumentSemanticTokensFull params = whenActiveRequest $ \conf
498532 Nothing <- gets LSPConf (lookup params. textDocument. uri . semanticTokensSentFiles)
499533 | Just tokens => pure $ pure $ (make $ tokens)
500534 withURI conf params. textDocument. uri Nothing (pure $ Left (MkResponseError RequestCancelled " Document Errors" JNull )) $ do
535+ logI Channel " Loading semantic tokens for file: \{show (params.textDocument.uri)}"
536+ clock0 <- coreLift (clockTime Monotonic )
537+ let fpath = uriPathToSystemPath params. textDocument. uri. path
538+ Right src <- coreLift $ File . ReadWrite . readFile fpath
539+ | Left err => pure $ Left (MkResponseError RequestCancelled " Couldn't read the file" JNull )
501540 md <- get MD
502- src <- getSource
503541 let srcLines = lines src
504542 let getLineLength = \ lineNum => maybe 0 (cast . length ) $ elemAt srcLines (integerToNat (cast lineNum))
505543 tokens <- getSemanticTokens md getLineLength
506544 update LSPConf ({ semanticTokensSentFiles $= insert params. textDocument. uri tokens })
545+ clock1 <- coreLift (clockTime Monotonic )
546+ let dif = timeDifference clock1 clock0
547+ logI Channel " Loading semantic tokens finished in \{show dif.milliseconds}ms"
507548 pure $ pure $ (make $ tokens)
508549handleRequest WorkspaceExecuteCommand
509550 (MkExecuteCommandParams partialResultToken " repl" (Just [json])) = whenActiveRequest $ \ conf => do
@@ -578,7 +619,6 @@ handleNotification TextDocumentDidSave params = whenActiveNotification $ \conf =
578619 logI Channel " Received didSave notification for \{show params.textDocument.uri}"
579620 update LSPConf (
580621 { dirtyFiles $= delete params. textDocument. uri
581- , errorFiles $= delete params. textDocument. uri
582622 , semanticTokensSentFiles $= delete params. textDocument. uri
583623 })
584624 ignore $ loadURI conf params. textDocument. uri Nothing
@@ -600,8 +640,7 @@ handleNotification TextDocumentDidChange params = whenActiveNotification $ \conf
600640
601641handleNotification TextDocumentDidClose params = whenActiveNotification $ \ conf => do
602642 logI Channel " Received didClose notification for \{show params.textDocument.uri}"
603- update LSPConf ({ openFile : = Nothing
604- , quickfixes : = []
643+ update LSPConf ({ quickfixes : = []
605644 , cachedActions : = empty
606645 , cachedHovers : = empty
607646 , dirtyFiles $= delete params. textDocument. uri
@@ -614,3 +653,4 @@ handleNotification TextDocumentDidClose params = whenActiveNotification $ \conf
614653
615654handleNotification method params = whenActiveNotification $ \ conf =>
616655 logW Channel " Received unhandled notification for method \{stringify $ toJSON method}"
656+
0 commit comments