-
Notifications
You must be signed in to change notification settings - Fork 8
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
Support multiple source directories #1
Conversation
elm-package.json may specify multiple source directories for a single Elm project (e.g. application modules and library modules). Modules in one source directory may import modules in another source directory transparently. With this change, we now find the elm-package.json file responsible for the requested module and use it to search all of the project’s source directories for each dependency.
We’re hoping to get this merged and released in elm-webpack-loader (via node-elm-compiler), so that we can use |
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.
Thanks for your PR ❤️. Code looks great. I had just one minor comment.
index.js
Outdated
} | ||
} | ||
|
||
// Given a source directory (containing top-level Elm modules), locate the | ||
// elm-package.json file that includes it. | ||
function findElmPackage(baseDir, currentDir) { |
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.
🎨 we can drop currentDir
and just use one arg.
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.
My intent here was to preserve baseDir
through the recursion so that when we found the elm-package.json file, we could verify that the baseDir
in question was actually listed in its source-directories
, but I ended up not writing this check. What do you think? Would this level of robustness be useful? Or is it sufficient just to search up through parent directories and use the first elm-package.json file that we find (in which case I will delete the unneeded variable).
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.
Thinking about it some more, I’m thinking we probably should check that the source-directories
does contain baseDir
. If not, and the elm-package.json contains source directories that don’t match, find-elm-dependencies is going to be unable to find any dependencies in that baseDir
, and it will be really confusing.
I’ll update this and include a test case.
@stoeffel OK, should be good to go now. |
Important to note this changes the API signature for the exported |
@sentience The cli doesn't work anymore. $ ./bin/cli.js ./test/fixtures/Parent.elm
[] Would you mind fixing that? Let me know if you need help. |
index.js
Outdated
if (typeof currentDir === "undefined") { | ||
currentDir = baseDir; | ||
} | ||
|
||
var elmPackagePath = path.join(currentDir, 'elm-package.json'); | ||
if (fs.existsSync(elmPackagePath)) { | ||
return elmPackagePath; | ||
var sourceDirectories = getSourceDirectories(elmPackagePath); | ||
if (_.includes(sourceDirectories, baseDir)) { |
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.
I'm worried that this never halts, when this isn't true. I think this should raise an error. I also think that the source-directories don't have to include base dir right? You could have a elm-package with only ./src
.
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.
It will halt when the search for a matching elm-package.json reaches the root directory of the file system (see return false;
on line 89).
Basically we ignore the “bad” elm-package.json file and continue searching up the path for a “good” elm-package.json file. If we never find one, we give up when we get to the filesystem root.
Hope that makes sense!
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.
Makes sense, but:
I also think that the source-directories don't have to include base dir right? You could have a elm-package with only ./src.
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.
Correct, and that’s supported by my implementation already. If you have:
my-package
`- elm-package.json ("source-directories": ["./src"])
`- src
`- Main.elm (module Main exposing (..))
…then getBaseDir('/path/to/src/Main.elm')
will return /path/to/src
, and then getElmPackageSourceDirectories('/path/to/src')
will find elm-package.json in the parent directory, confirm it includes ./src
in "source-directories"
and return ['/path/to/src']
.
Unless I’m missing something?
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.
Oh, you're right!
Taking a look at the CLI now. |
CLI is fixed. Good catch! |
Thanks for your contribution. |
published with v1.0.0 |
// elm-package.json file that includes it and get all its source directories. | ||
function getElmPackageSourceDirectories(baseDir, currentDir) { | ||
if (typeof currentDir === "undefined") { | ||
currentDir = baseDir = path.resolve(baseDir); |
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.
Please set this on multiple lines, this is prone to error.
} | ||
|
||
if (isRoot(currentDir)) { | ||
return false; |
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.
What is the type of this function meant to be? Make it return an empty list instead of a bool.
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.
Good catch!
|
||
function findAllDependenciesHelp(file, knownDependencies, baseDir, knownFiles) { | ||
function getSourceDirectories(elmPackagePath) { | ||
var elmPackage = JSON.parse(fs.readFileSync(elmPackagePath, 'utf8')); |
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 will crash if there is invalid json, with a bad error message. Good to catch it and return an empty list instead.
_.find(sourceDirectories, function(sourceDir) { | ||
var absPath = path.join(sourceDir, dependencyLogicalName + extension); | ||
if (fs.existsSync(absPath)) { | ||
result = absPath; |
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.
why use mutation? Do result = _.find(...)
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.
The mutation avoids having to either map
all entries to absolute paths, or having to map the found result a second time after returning it. I'm happy to go with either one if you consider this an unwanted optimisation.
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.
I'd rather spend milliseconds on avoiding crashes than hours debugging :)
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.
👍
@sentience I have some concerns with the code that I'd like addressed before using the webpack-loader to rely on this. I've commented on the diff. |
Thanks for the review! I'll open a second PR with the requested improvements to release as 1.0.1. |
elm-package.json may specify multiple source directories for a single Elm project (e.g. application modules and library modules). Modules in one source directory may import modules in another source directory transparently.
With this change, we now find the elm-package.json file responsible for the requested module and use it to search all of the project’s source directories for each dependency.