Skip to content
This repository was archived by the owner on Mar 22, 2021. It is now read-only.
This repository was archived by the owner on Mar 22, 2021. It is now read-only.

Call to getCodeActions needs to wait - for tests #80

Open
@gdevanla

Description

@gdevanla

There were some non-deterministic failures/success in tests that was initially observed here haskell/ghcide#913 (comment).

Therefore, I created a simpler example to demonstrate the issue. The issue is when there is a parse error reported in Diagnostics, then sometimes the first call to getCodeActions returns a empty list. But, calling it the second time returns a list of code actions.

Here is a simple example that reproduces the issue:

extendImportTests :: TestTree                                                                                                                                                                                       
extendImportTests = testGroup "extend import actions"                                                                                                                                                               
  [ testSession "extend single line import with value" $ template                                                                                                                                                   
      (T.unlines                                                                                                                                                                                                    
            [ "module ModuleA where ()"      --- <-  The parse error is here                                                                                                                                                                        
            ])                                                                                                                                                                                                      
      (T.unlines                                                                                                                                                                                   Add TODO2 Item   
            [ "module ModuleB where"                                                                                                                                                              Add TODO Item 1   
            , "import Data.Map ()"                                                                                                                                                                                  
            , "foo = fromList []"                                                                                                                                                                                   
            ])                                                                                                                                                                                                      
      (Range (Position 3 17) (Position 3 18))                                                                                                                                                                       
      "Add stuffA to the import list of ModuleA"                                                                                                                                                                    
      (T.unlines                                                                                                                                                                                                    
            [ "module ModuleB where"                                                                                                                                                                                
            , "import ModuleA as A (stuffA, stuffB)"                                                                                                                                                                
            , "main = print (stuffA, stuffB)"                                                                                                                                                                       
            ])                                                                                                                                                                                                      
  ]                                                                                                                                                                                                                 
  where                                                                                                                                                                                                             
    template contentA contentB range expectedAction expectedContentB = do                                                                                                                                           
      _docA <- createDoc "ModuleA.hs" "haskell" contentA                                                                                                                                                            
      docB <- createDoc "ModuleB.hs" "haskell" contentB                                                                                                                                                             
      diag <- waitForDiagnostics                                                                                                                                                                                    
      liftIO $ putStrLn $ "Showing Diagnostics"                                                                                                                                                                     
      liftIO $ putStrLn $ show diag                                                                                                                                                                                 
      liftIO $ putStrLn $ "getCodeActions called first time"                                                                                                                                                        
      codeActions_1 <- getCodeActions docB range                                                                                                                                                                    
      liftIO $ putStrLn $ show $ length codeActions_1                                                                                                                                                               
      liftIO $ putStrLn $ "getCodeActions called second time"                                                                                                                                                       
      codeActions_2 <- getCodeActions docB range                                                                                                                                                                    
      liftIO $ putStrLn $ show $ length codeActions_2     

Here are the non-deterministic results. Notice, 0 and 60 is first run, whereas we have 60 and 60 in second run.

#  ~/fsf/hls/ghcide on git:master x 
$ time stack test --test-arguments '--pattern "extend import actions"' --fast 
ghcide> test (suite: ghcide-tests, args: --pattern "extend import actions")

ghcide> ghcide
ghcide>   code actions
ghcide>     extend import actions
ghcide>       extend single line import with value: Showing Diagnostics
ghcide> [Diagnostic {_range = Range {_start = Position {_line = 0, _character = 21}, _end = Position {_line = 0, _character = 23}}, _severity = Just DsError, _code = Nothing, _source = Just "typecheck", _message = "Parse error: module header, import declaration\nor top-level declaration expected.", _tags = Nothing, _relatedInformation = Nothing}]
ghcide> getCodeActions called first time
ghcide> 0
ghcide> getCodeActions called second time
ghcide> 60
ghcide> OK (2.13s)
ghcide> 
ghcide> All 1 tests passed (2.13s)
ghcide> Test suite ghcide-tests passed
stack test --test-arguments '--pattern "extend import actions"' --fast  1.94s user 0.61s system 100% cpu 2.524 total

#  ~/fsf/hls/ghcide on git:master x 
$ time stack test --test-arguments '--pattern "extend import actions"' --fast 
ghcide> test (suite: ghcide-tests, args: --pattern "extend import actions")

ghcide> ghcide
ghcide>   code actions
ghcide>     extend import actions
ghcide>       extend single line import with value: Showing Diagnostics
ghcide> [Diagnostic {_range = Range {_start = Position {_line = 2, _character = 6}, _end = Position {_line = 2, _character = 14}}, _severity = Just DsError, _code = Nothing, _source = Just "typecheck", _message = "\8226 Variable not in scope: fromList :: [a0] -> t\n\8226 Perhaps you want to add \8216fromList\8217 to the import list\n  in the import of \8216Data.Map\8217\n  (/tmp/extra-dir-2462899497006/ModuleB.hs:2:1-18).", _tags = Nothing, _relatedInformation = Nothing}]
ghcide> getCodeActions called first time
ghcide> 60
ghcide> getCodeActions called second time
ghcide> 60
ghcide> OK (2.63s)
ghcide> 
ghcide> All 1 tests passed (2.63s)
ghcide> Test suite ghcide-tests passed
stack test --test-arguments '--pattern "extend import actions"' --fast  2.61s user 0.61s system 106% cpu 3.034 total

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions