-
-
Notifications
You must be signed in to change notification settings - Fork 392
Use relative file paths for HIE files and Stan's config maps #4023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9509b27
4e95308
802b46c
c0dac2e
e6a8520
430c82d
36e8877
afa2b9b
188c767
d028cd6
fc2aff0
1c5e034
c24f564
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,68 +2,47 @@ | |
{-# LANGUAGE PatternSynonyms #-} | ||
module Ide.Plugin.Stan (descriptor, Log) where | ||
|
||
import Compat.HieTypes (HieASTs, HieFile (..)) | ||
import Control.DeepSeq (NFData) | ||
import Control.Monad (void, when) | ||
import Control.Monad.IO.Class (liftIO) | ||
import Control.Monad.Trans.Maybe (MaybeT (MaybeT), runMaybeT) | ||
import Data.Default | ||
import Data.Foldable (toList) | ||
import Data.Hashable (Hashable) | ||
import qualified Data.HashMap.Strict as HM | ||
import Data.HashSet (HashSet) | ||
import qualified Data.HashSet as HS | ||
import qualified Data.Map as Map | ||
import Data.Maybe (fromJust, mapMaybe, | ||
maybeToList) | ||
import Data.String (IsString (fromString)) | ||
import qualified Data.Text as T | ||
import Compat.HieTypes (HieFile (..)) | ||
import Control.DeepSeq (NFData) | ||
import Control.Monad (void) | ||
import Control.Monad.IO.Class (liftIO) | ||
import Data.Foldable (toList) | ||
import Data.Hashable (Hashable) | ||
import qualified Data.HashMap.Strict as HM | ||
import Data.Maybe (mapMaybe) | ||
import qualified Data.Text as T | ||
import Development.IDE | ||
import Development.IDE.Core.Rules (getHieFile, | ||
getSourceFileSource) | ||
import Development.IDE.Core.RuleTypes (HieAstResult (..)) | ||
import qualified Development.IDE.Core.Shake as Shake | ||
import Development.IDE.GHC.Compat (HieASTs (HieASTs), | ||
HieFile (hie_hs_file), | ||
RealSrcSpan (..), mkHieFile', | ||
mkRealSrcLoc, mkRealSrcSpan, | ||
runHsc, srcSpanEndCol, | ||
srcSpanEndLine, | ||
srcSpanStartCol, | ||
srcSpanStartLine, tcg_exports) | ||
import Development.IDE.GHC.Error (realSrcSpanToRange) | ||
import GHC.Generics (Generic) | ||
import Ide.Plugin.Config (PluginConfig (..)) | ||
import Ide.Types (PluginDescriptor (..), | ||
PluginId, configHasDiagnostics, | ||
configInitialGenericConfig, | ||
defaultConfigDescriptor, | ||
defaultPluginDescriptor) | ||
import qualified Language.LSP.Protocol.Types as LSP | ||
import Stan (createCabalExtensionsMap, | ||
getStanConfig) | ||
import Stan.Analysis (Analysis (..), runAnalysis) | ||
import Stan.Category (Category (..)) | ||
import Stan.Cli (StanArgs (..)) | ||
import Stan.Config (Config, ConfigP (..), | ||
applyConfig, defaultConfig) | ||
import Stan.Config.Pretty (ConfigAction, configToTriples, | ||
prettyConfigAction, | ||
prettyConfigCli) | ||
import Stan.Core.Id (Id (..)) | ||
import Stan.EnvVars (EnvVars (..), envVarsToText) | ||
import Stan.Inspection (Inspection (..)) | ||
import Stan.Inspection.All (inspectionsIds, inspectionsMap) | ||
import Stan.Observation (Observation (..)) | ||
import Stan.Report.Settings (OutputSettings (..), | ||
ToggleSolution (..), | ||
Verbosity (..)) | ||
import Stan.Toml (usedTomlFiles) | ||
import System.Directory (makeRelativeToCurrentDirectory) | ||
import Trial (Fatality, Trial (..), fiasco, | ||
pattern FiascoL, | ||
pattern ResultL, prettyTrial, | ||
prettyTrialWith) | ||
import Development.IDE.Core.Rules (getHieFile) | ||
import qualified Development.IDE.Core.Shake as Shake | ||
import GHC.Generics (Generic) | ||
import Ide.Plugin.Config (PluginConfig (..)) | ||
import Ide.Types (PluginDescriptor (..), PluginId, | ||
configHasDiagnostics, | ||
configInitialGenericConfig, | ||
defaultConfigDescriptor, | ||
defaultPluginDescriptor) | ||
import qualified Language.LSP.Protocol.Types as LSP | ||
import Stan (createCabalExtensionsMap, | ||
getStanConfig) | ||
import Stan.Analysis (Analysis (..), runAnalysis) | ||
import Stan.Category (Category (..)) | ||
import Stan.Cli (StanArgs (..)) | ||
import Stan.Config (Config, ConfigP (..), applyConfig) | ||
import Stan.Config.Pretty (prettyConfigCli) | ||
import Stan.Core.Id (Id (..)) | ||
import Stan.EnvVars (EnvVars (..), envVarsToText) | ||
import Stan.Inspection (Inspection (..)) | ||
import Stan.Inspection.All (inspectionsIds, inspectionsMap) | ||
import Stan.Observation (Observation (..)) | ||
import Stan.Report.Settings (OutputSettings (..), | ||
ToggleSolution (..), | ||
Verbosity (..)) | ||
import Stan.Toml (usedTomlFiles) | ||
import System.Directory (makeRelativeToCurrentDirectory) | ||
import Trial (Fatality, Trial (..), fiasco, | ||
pattern FiascoL, pattern ResultL, | ||
prettyTrial, prettyTrialWith) | ||
|
||
descriptor :: Recorder (WithPriority Log) -> PluginId -> PluginDescriptor IdeState | ||
descriptor recorder plId = (defaultPluginDescriptor plId desc) | ||
{ pluginRules = rules recorder plId | ||
|
@@ -164,24 +143,25 @@ rules recorder plId = do | |
logWith recorder Debug (LogDebugStanEnvVars env) | ||
seTomlFiles <- liftIO $ usedTomlFiles useDefConfig (stanArgsConfigFile stanArgs) | ||
|
||
(cabalExtensionsMap, checksMap, confIgnored) <- case configTrial of | ||
-- Note that Stan works in terms of relative paths, but the HIE come in as absolute. Without | ||
-- making its path relative, the file name(s) won't line up with the associated Map keys. | ||
relativeHsFilePath <- liftIO $ makeRelativeToCurrentDirectory $ fromNormalizedFilePath file | ||
let hieRelative = hie{hie_hs_file=relativeHsFilePath} | ||
|
||
(checksMap, ignoredObservations) <- case configTrial of | ||
FiascoL es -> do | ||
logWith recorder Development.IDE.Warning (LogWarnConf es) | ||
pure (Map.empty, | ||
HM.fromList [(LSP.fromNormalizedFilePath file, inspectionsIds)], | ||
[]) | ||
ResultL warnings stanConfig -> do | ||
let currentHSAbs = fromNormalizedFilePath file -- hie_hs_file hie | ||
currentHSRel <- liftIO $ makeRelativeToCurrentDirectory currentHSAbs | ||
cabalExtensionsMap <- liftIO $ createCabalExtensionsMap isLoud (stanArgsCabalFilePath stanArgs) [hie] | ||
|
||
-- Files (keys) in checksMap need to have an absolute path for the analysis, but applyConfig needs to receive relative | ||
-- filepaths to apply the config, because the toml config has relative paths. Stan itself seems to work only in terms of relative paths. | ||
let checksMap = HM.mapKeys (const currentHSAbs) $ applyConfig [currentHSRel] stanConfig | ||
|
||
let analysis = runAnalysis cabalExtensionsMap checksMap (configIgnored stanConfig) [hie] | ||
pure (cabalExtensionsMap, checksMap, configIgnored stanConfig) | ||
let analysis = runAnalysis cabalExtensionsMap checksMap confIgnored [hie] | ||
-- If we can't read the config file, default to using all inspections: | ||
let allInspections = HM.fromList [(relativeHsFilePath, inspectionsIds)] | ||
pure (allInspections, []) | ||
ResultL _warnings stanConfig -> do | ||
-- HashMap of *relative* file paths to info about enabled checks for those file paths. | ||
let checksMap = applyConfig [relativeHsFilePath] stanConfig | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I checked both This seemed to have been causing the miss in the Map lookup. (e.g. looking for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be the reason why I initially had issues with relative/absolute paths. Thanks for the investigation! |
||
pure (checksMap, configIgnored stanConfig) | ||
|
||
-- A Map from *relative* file paths (just one, in this case) to language extension info: | ||
cabalExtensionsMap <- liftIO $ createCabalExtensionsMap isLoud (stanArgsCabalFilePath stanArgs) [hieRelative] | ||
let analysis = runAnalysis cabalExtensionsMap checksMap ignoredObservations [hieRelative] | ||
return (analysisToDiagnostics file analysis, Just ()) | ||
else return ([], Nothing) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
data A = A Int Int | ||
|
||
a = length [1..] | ||
|
||
b = undefined |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module CabalFileTest () where | ||
|
||
-- With `StrictData` enabled in the `.cabal` file, Stan shouldn't complain here: | ||
data A = A Int Int | ||
|
||
-- ...but it should still complain here! | ||
kewlFunc = undefined |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
cabal-version: 3.0 | ||
name: cabal-file-test | ||
version: 0.0.0.0 | ||
|
||
library | ||
exposed-modules: CabalFileTest | ||
hs-source-dirs: extensions-cabal-file | ||
-- Specifically, we're testing that Stan respects the following extension definition: | ||
default-extensions: StrictData |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{-# LANGUAGE StrictData #-} | ||
|
||
module LanguagePragmaTest () where | ||
|
||
-- With the above `StrictData` language pragma, Stan shouldn't complain here: | ||
data A = A Int Int | ||
|
||
-- ...but it should still complain here! | ||
kewlFunc = undefined |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
cabal-version: 3.0 | ||
name: language-pragma-test | ||
version: 0.0.0.0 | ||
|
||
-- Without at least a minimal valid `.cabal` file, Stan won't bother building its | ||
-- map of language extensions. This means it also won't detect LANGUAGE pragmas | ||
-- without this file. | ||
|
||
library | ||
exposed-modules: LanguagePragmaTest | ||
hs-source-dirs: extensions-language-pragma |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This didn't seem to be the case, when I looked?
I think this logic was added in #3914 ... perhaps @0rphee could confirm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this was added in that PR. As I remember it, If I used relative paths, it didn't work, because of how an internal function works in
runAnalysis
, that checks if an absolute path to a file, begins with another filepath, (currentHSAbs
I think?).