Skip to content
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 paths relative to the root directory #727

Merged
merged 7 commits into from Nov 28, 2019
Merged

Conversation

pepicrft
Copy link
Contributor

Short description πŸ“

This PR adds support for defining paths relative to the root directory. The paths can be initialized with .relativeToRoot("file.swift") or just prefixing the string with two slashes: //file.swift.

Implementation πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

  • Add the new case to Path.
  • Extend GeneratorPaths.
  • Add unit & acceptance tests.

@pepicrft pepicrft requested review from andreacipriani and a team November 27, 2019 17:54
@pepicrft pepicrft self-assigned this Nov 27, 2019
@ghost ghost requested review from kwridan and marciniwanicki and removed request for a team November 27, 2019 17:54
@github-actions
Copy link
Contributor

@pepibumur your pull request is missing a changelog!

@pepicrft
Copy link
Contributor Author

I think you'll love this one @andreacipriani

Copy link
Collaborator

@kwridan kwridan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work πŸ‘

Sources/ProjectDescription/Path.swift Show resolved Hide resolved
docs/usage/projectswift.mdx Show resolved Hide resolved
@@ -15,13 +34,18 @@ struct GeneratorPaths {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this instance, performing a root look up per resolve call seems unnecessary - the root path is unlikely to change during the generation process especially for an individual project which is the scope of the GeneratorPaths struct usage. As such we can pass in the rootPath in the initialiser and do the lookup once at the model loader.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the root path is unlikely to change during the generation

The path depends on the project and different projects might have different root directories because we support multiple Tuist directories. For that reason I added the look up using the RootDirectoryLocator, which optimizes the lookups using the cache.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a terrible job explaining this πŸ˜› - it's ok we can improve separately if needed

GeneratorModelLoader.swift#L44 creates the GeneratorPaths struct per project load as such it could be tweaked:

 func loadProject(at path: AbsolutePath) throws -> TuistCore.Project {
      let manifest = try manifestLoader.loadProject(at: path)
      let rootPath = RootDirectoryLocator.shared.locate(from: path)
      let generatorPaths = GeneratorPaths(manifestDirectory: path, rootPath: rootPath)
     // ...

That way inside we don't need to do lookups per resolve (true it's cached under the hood, however not needed).

Was a minor comment - no worries

@@ -15,6 +15,12 @@ final class RootDirectoryLocator: RootDirectoryLocating {
/// This cache avoids having to traverse the directories hierarchy every time the locate method is called.
fileprivate var cache: [AbsolutePath: AbsolutePath] = [:]

/// Shared instance
static var shared: RootDirectoryLocating = RootDirectoryLocator()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor/personal opinion here - please take my comments with a pinch of salt πŸ§‚]

I appreciate we need to maintain a single instance to leverage and benefit from the caching the RootDirectoryLocator performs internally.

Sadly having shared instances makes it really easy to access those components which may have side effects from anywhere in the codebase. E.g. like in the generator paths struct earlier ... I am perhaps more accustomed to assembly style DI practices like the one suggested by @marciniwanicki in #351 to solve these kind of problems - but I digress.

Seeing we have adopted shared instances elsewhere to solve this, having this defined as one keeps things consistent - we should use them judiciously and with care.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor/personal opinion here - please take my comments with a pinch of salt πŸ§‚]

Thanks for keep sharing those because it's always better to have always different points of view.

I think dependency injection is another valid approach, but I had to make a trade-off here (like most of the times in programming). The risk of having shared instances that hold state is that they might have side effects that might get out of control. I think it's not the case of RootDirectoryLocator where the state is private and changes in the state are not relevant to the rest of the code base.

Dependency injection comes with its downsides too. Swift doesn't make things easier and that results in some boilerplate code that is hard to reason about. In my experience, I always find very hard o reason about injected dependencies (unless they were injected through the constructor). When we build abstractions for easing dependency injection, or taking it to a whole new level, reasoning about the code becomes really hard: what am I getting here? who is injecting the dependency?, from where is the dependency injected?

I'm happy to reconsider the approach if we see the current one resulting in side effects that make the code execution go through unexpected paths. Given the amount of global dependencies that we have at the moment, and the fact that they are not seeing big issues with it, I'd not focus on this at the moment.

@andreacipriani
Copy link
Contributor

@pepibumur I'll try it as soon as it's merged

@pepicrft pepicrft merged commit 8635579 into master Nov 28, 2019
@pepicrft pepicrft deleted the from-root-directory branch November 28, 2019 13:43
@pepicrft pepicrft mentioned this pull request Dec 17, 2019
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants