packages feed

hls-module-name-plugin 1.0.0.1 → 1.0.0.2

raw patch · 4 files changed

+32/−21 lines, 4 filesdep ~ghcide

Dependency ranges changed: ghcide

Files

hls-module-name-plugin.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               hls-module-name-plugin-version:            1.0.0.1+version:            1.0.0.2 synopsis:           Module name plugin for Haskell Language Server description:   Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>@@ -25,7 +25,7 @@     , base                  >=4.12 && <5     , directory     , filepath-    , ghcide                >=1.2  && <1.5+    , ghcide                >=1.2  && <1.6     , hls-plugin-api        >=1.1  && <1.3     , lsp     , text
src/Ide/Plugin/ModuleName.hs view
@@ -21,7 +21,7 @@ import           Data.Aeson                 (Value (Null), toJSON) import           Data.Char                  (isLower) import qualified Data.HashMap.Strict        as HashMap-import           Data.List                  (find, intercalate, isPrefixOf)+import           Data.List                  (intercalate, isPrefixOf, minimumBy) import           Data.Maybe                 (maybeToList) import           Data.String                (IsString) import qualified Data.Text                  as T@@ -32,7 +32,7 @@                                              uriToFilePath', use, use_) import           Development.IDE.GHC.Compat (GenLocated (L), getSessionDynFlags,                                              hsmodName, importPaths,-                                             pattern OldRealSrcSpan,+                                             pattern RealSrcSpan,                                              pm_parsed_source, unLoc) import           Ide.Types import           Language.LSP.Server@@ -44,6 +44,7 @@ import           System.Directory           (canonicalizePath) import           System.FilePath            (dropExtension, splitDirectories,                                              takeFileName)+import Data.Ord (comparing)  -- |Plugin descriptor descriptor :: PluginId -> PluginDescriptor IdeState@@ -97,42 +98,46 @@     contents <- lift . getVirtualFile $ toNormalizedUri uri     let emptyModule = maybe True (T.null . T.strip . virtualFileText) contents -    correctName <- MaybeT . liftIO $ traceAs "correctName" <$> pathModuleName state nfp fp+    correctNames <- liftIO $ traceAs "correctNames" <$> pathModuleNames state nfp fp+    let bestName = minimumBy (comparing T.length) correctNames      statedNameMaybe <- liftIO $ traceAs "statedName" <$> codeModuleName state nfp     case statedNameMaybe of       Just (nameRange, statedName)-        | correctName /= statedName ->-            pure $ Replace uri nameRange ("Set module name to " <> correctName) correctName+        | statedName `notElem` correctNames ->+            pure $ Replace uri nameRange ("Set module name to " <> bestName) bestName       Nothing         | emptyModule ->-            let code = "module " <> correctName <> " where\n"+            let code = "module " <> bestName <> " where\n"             in pure $ Replace uri (Range (Position 0 0) (Position 0 0)) code code       _ -> MaybeT $ pure Nothing --- | The module name, as derived by the position of the module in its source directory-pathModuleName :: IdeState -> NormalizedFilePath -> String -> IO (Maybe T.Text)-pathModuleName state normFilePath filePath-  | isLower . head $ takeFileName filePath = return $ Just "Main"+-- | Possible module names, as derived by the position of the module in the+-- source directories.  There may be more than one possible name, if the source+-- directories are nested inside each other.+pathModuleNames :: IdeState -> NormalizedFilePath -> String -> IO [T.Text]+pathModuleNames state normFilePath filePath+  | isLower . head $ takeFileName filePath = return ["Main"]   | otherwise = do       session <- runAction "ModuleName.ghcSession" state $ use_ GhcSession normFilePath       srcPaths <- evalGhcEnv (hscEnvWithImportPaths session) $ importPaths <$> getSessionDynFlags       paths <- mapM canonicalizePath srcPaths       mdlPath <- canonicalizePath filePath-      pure $ do-        prefix <- find (`isPrefixOf` mdlPath) paths-        pure-          . T.pack-          . intercalate "."-          . splitDirectories-          . drop (length prefix + 1)-          $ dropExtension mdlPath+      let prefixes = filter (`isPrefixOf` mdlPath) paths+      pure (map (moduleNameFrom mdlPath) prefixes)+  where+    moduleNameFrom mdlPath prefix =+      T.pack+        . intercalate "."+        . splitDirectories+        . drop (length prefix + 1)+        $ dropExtension mdlPath  -- | The module name, as stated in the module codeModuleName :: IdeState -> NormalizedFilePath -> IO (Maybe (Range, T.Text)) codeModuleName state nfp = runMaybeT $ do   pm <- MaybeT . runAction "ModuleName.GetParsedModule" state $ use GetParsedModule nfp-  L (OldRealSrcSpan l) m <- MaybeT . pure . hsmodName . unLoc $ pm_parsed_source pm+  L (RealSrcSpan l _) m <- MaybeT . pure . hsmodName . unLoc $ pm_parsed_source pm   pure (realSrcSpanToRange l, T.pack $ show m)  -- traceAs :: Show a => String -> a -> a
test/Main.hs view
@@ -32,6 +32,11 @@       [CodeLens { _command = Just c }] <- getCodeLenses doc       executeCommand c       void $ skipManyTill anyMessage (message SWorkspaceApplyEdit)++  , goldenWithModuleName "Fix wrong module name in nested directory" "subdir/TWrongModuleName" $ \doc -> do+      [CodeLens { _command = Just c }] <- getCodeLenses doc+      executeCommand c+      void $ skipManyTill anyMessage (message SWorkspaceApplyEdit)   ]  goldenWithModuleName :: TestName -> FilePath -> (TextDocumentIdentifier -> Session ()) -> TestTree
test/testdata/hie.yaml view
@@ -1,6 +1,7 @@ cradle:   direct:     arguments:+      - "-isubdir"       - "TEmptyModule"       - "TWrongModuleName"       - "mainlike"