@@ -67,7 +67,7 @@ data AddParams = AddParams
67
67
{ rootDirParam :: FilePath -- ^ The root directory.
68
68
, fileParam :: ModulePath -- ^ A path to a module inside the
69
69
-- library/executable/test-suite you want to
70
- -- add the package to. May be a realtive oir
70
+ -- add the package to. May be a relative or
71
71
-- absolute path, thus, must be normalised.
72
72
, packageParam :: Package -- ^ The name of the package to add.
73
73
}
@@ -76,7 +76,7 @@ data AddParams = AddParams
76
76
-- | FilePath to a cabal package description file.
77
77
type CabalFilePath = FilePath
78
78
-- | FilePath to a package.yaml package description file.
79
- type PackageYamlFilePath = FilePath
79
+ type HpackFilePath = FilePath
80
80
-- | FilePath to a module within the project.
81
81
-- May be used to establish what component the dependency shall be added to.
82
82
type ModulePath = FilePath
@@ -88,8 +88,14 @@ type Package = T.Text
88
88
-- Supported are `*.cabal` and `package.yaml` specifications.
89
89
-- Moreover, may fail with an IOException in case of a filesystem problem.
90
90
addCmd :: CommandFunc AddParams J. WorkspaceEdit
91
- addCmd = CmdSync $ \ ( AddParams rootDir modulePath pkg) -> do
91
+ addCmd = CmdSync addCmd'
92
92
93
+ -- | Add a package to the project's dependencies.
94
+ -- May fail if no project dependency specification can be found.
95
+ -- Supported are `*.cabal` and `package.yaml` specifications.
96
+ -- Moreover, may fail with an IOException in case of a filesystem problem.
97
+ addCmd' :: AddParams -> IdeGhcM (IdeResult J. WorkspaceEdit )
98
+ addCmd' (AddParams rootDir modulePath pkg) = do
93
99
packageType <- liftIO $ findPackageType rootDir
94
100
fileMap <- GM. mkRevRedirMapFunc
95
101
@@ -105,9 +111,10 @@ addCmd = CmdSync $ \(AddParams rootDir modulePath pkg) -> do
105
111
liftToGhc $ editHpackPackage absFp relModulePath pkg
106
112
NoPackage -> return $ IdeResultFail (IdeError PluginError " No package.yaml or .cabal found" Null )
107
113
108
- data PackageType = CabalPackage FilePath -- ^ Location of Cabal File.
109
- | HpackPackage FilePath -- ^ Location of `package.yaml`
114
+ data PackageType = CabalPackage FilePath -- ^ Location of Cabal File. May be relative.
115
+ | HpackPackage FilePath -- ^ Location of `package.yaml`. May be relative.
110
116
| NoPackage -- ^ No package format has been found.
117
+ deriving (Show , Eq )
111
118
112
119
-- | Find the package type the project with the given root uses.
113
120
-- Might have weird results if there is more than one cabal package specification
@@ -129,12 +136,13 @@ findPackageType rootDir = do
129
136
return $ fromMaybe NoPackage $ asum [HpackPackage <$> mHpack, CabalPackage <$> mCabal]
130
137
131
138
-- | Edit a hpack package to add the given package to the package.yaml.
139
+ -- If package.yaml is not in an expected format, will fail fatally.
132
140
--
133
141
-- Currently does not preserve format.
134
142
-- Keep an eye out on this other GSOC project!
135
143
-- https://github.com/wisn/format-preserving-yaml
136
- editHpackPackage :: PackageYamlFilePath -- ^ Path to the package.yaml file
137
- -- containing the package description.
144
+ editHpackPackage :: HpackFilePath -- ^ Path to the package.yaml file
145
+ -- containing the package description.
138
146
-> ModulePath -- ^ Path to the module where the command has
139
147
-- been issued in.
140
148
-- Used to find out what component the
@@ -148,19 +156,29 @@ editHpackPackage fp modulePath pkgName = do
148
156
149
157
case Y. decodeThrow contents :: Maybe Object of
150
158
Just obj -> do
159
+ -- Map over all major components, such as "executable", "executables",
160
+ -- "tests" and "benchmarks". Note, that "library" is a major component,
161
+ -- but its structure is different and can not be mapped over in the same way.
162
+ --
163
+ -- Only adds the package if the declared "source-dirs" field is part of the
164
+ -- module path, or if no "source-dirs" is declared.
151
165
let compsMapped = mapComponentTypes (ensureObject $ mapComponents (ensureObject $ mapCompDependencies addDep)) obj
152
166
153
- let addDepToMainLib = fromMaybe True $ do
154
- Object lib <- HM. lookup " library " compsMapped
155
- sourceDirs <- HM. lookup " source-dirs " lib
156
- return $ isInSourceDir sourceDirs
167
+ -- Is there a global "dependencies" yaml object?
168
+ let addDepToMainDep = fromMaybe False $ do
169
+ Array _ <- HM. lookup " dependencies " compsMapped
170
+ return True
157
171
158
- let newPkg = if addDepToMainLib
159
- then mapMainDependencies addDep compsMapped
160
- else compsMapped
172
+ -- Either add the package to only the top-level "dependencies",
173
+ -- or to all main components of which the given module is part of.
174
+ let newPkg
175
+ | addDepToMainDep = mapMainDependencies addDep obj
176
+ -- Map over the library component at last, since it has different structure.
177
+ | otherwise = mapLibraryDependency addDep compsMapped
161
178
162
- newPkgText = T. decodeUtf8 $ Y. encode newPkg
179
+ let newPkgText = T. decodeUtf8 $ Y. encode newPkg
163
180
181
+ -- Construct the WorkSpaceEdit
164
182
let numOldLines = length $ T. lines $ T. decodeUtf8 contents
165
183
range = J. Range (J. Position 0 0 ) (J. Position numOldLines 0 )
166
184
textEdit = J. TextEdit range newPkgText
@@ -179,10 +197,18 @@ editHpackPackage fp modulePath pkgName = do
179
197
180
198
mapMainDependencies :: (Value -> Value ) -> Object -> Object
181
199
mapMainDependencies f o =
182
- let g " dependencies" = f
200
+ let g :: T. Text -> Value -> Value
201
+ g " dependencies" = f
183
202
g _ = id
184
203
in HM. mapWithKey g o
185
204
205
+ mapLibraryDependency :: (Value -> Value ) -> Object -> Object
206
+ mapLibraryDependency f o =
207
+ let g :: T. Text -> Value -> Value
208
+ g " library" (Y. Object o') = Y. Object (mapCompDependencies f o')
209
+ g _ x = x
210
+ in HM. mapWithKey g o
211
+
186
212
mapComponentTypes :: (Value -> Value ) -> Object -> Object
187
213
mapComponentTypes f o =
188
214
let g " executables" = f
0 commit comments