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

Account for multiple project roots #1609

Merged
merged 18 commits into from
Mar 22, 2022
Merged

Account for multiple project roots #1609

merged 18 commits into from
Mar 22, 2022

Conversation

PEZ
Copy link
Collaborator

@PEZ PEZ commented Mar 20, 2022

Glob for all project roots in the workspace

Let the user pick if there are more than one
Changes the way we find the closest project root
Not using node fs module at all
Fixes #1254

My Calva PR Checklist

I have:

  • Read How to Contribute.
  • Directed this pull request at the dev branch. (Or have specific reasons to target some other branch.)
  • Made sure I have changed the PR base branch, so that it is not published. (Sorry for the nagging.)
  • Updated the [Unreleased] entry in CHANGELOG.md, linking the issue(s) that the PR is addressing.
  • Figured if anything about the fix warrants tests on Mac/Linux/Windows/Remote/Whatever, and either tested it there if so, or mentioned it in the PR.
  • Added to or updated docs in this branch, if appropriate
  • Tests
    • Tested the particular change
    • Figured if the change might have some side effects and tested those as well.
    • Smoke tested the extension as such.
    • Tested the VSIX built from the PR (so, after you've submitted the PR). You'll find the artifacts by clicking Show all checks in the CI section of the PR page, and then Details on the ci/circleci: build test.
  • Referenced the issue I am fixing/addressing in a commit message for the pull request.
  • Created the issue I am fixing/addressing, if it was not present.
  • Formatted all JavaScript and TypeScript code that was changed. (use the prettier extension or run npm run prettier-format)
  • Confirmed that there are no linter warnings or errors (use the eslint extension, run npm run eslint before creating your PR, or run npm run eslint-watch to eslint as you go).

Ping @PEZ, @bpringe

PEZ added 2 commits March 20, 2022 18:49
Let the user pick if there are more than one
Changes the way we find the closest project root
Not using node fs module at all
Fixes #1254
@PEZ PEZ requested review from bpringe, corasaurus-hex and Cyrik March 20, 2022 17:52
Copy link
Contributor

@corasaurus-hex corasaurus-hex left a comment

Choose a reason for hiding this comment

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

I had a couple questions but other than that this is beautiful 😚👌🏻

src/state.ts Outdated
async function findProjectRootPaths() {
const projectFileNames: string[] = ['project.clj', 'shadow-cljs.edn', 'deps.edn'];
const projectFilesGlob = `**/{${projectFileNames.join(',')}}`;
const excludeDirsGlob = `**/{${config.getConfig().projectRootsSearchExclude.join(',')}}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

I see target is in the list of excluded directories. Would that exclude a directory named target-files or does it need to be just target by itself in order to match this glob?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It will only exclude target, exactly as that. Wherever it appears, though...

src/state.ts Outdated
console.debug('glob took', new Date().getTime() - t0, 'ms');
const projectFilePaths = candidateUris.map((uri) => path.dirname(uri.fsPath));
const candidatePaths = [...new Set(projectFilePaths)];
console.log(candidatePaths);
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be cool to make this console.log({candidatePaths}) so the log entry contents are labeled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

TIL.

Wasn't intending to keep this logging in there, though. Except the timing of the glob, which could be good to be able to ask users about for a while.

src/state.ts Outdated
? candidatePaths
.filter((p) => docDir.startsWith(p))
.sort()
.reverse()[0]
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! That's a good way to find the longest match 😄

src/config.ts Outdated
@@ -161,6 +161,7 @@ function getConfig() {
useDeprecatedAliasFlag: configOptions.get<boolean>('jackIn.useDeprecatedAliasFlag'),
},
enableClojureLspOnStart: configOptions.get<boolean>('enableClojureLspOnStart'),
projectRootsSearchExclude: configOptions.get<string[]>('projectRootsSearchExclude'),
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh! I missed one thing! We should probably add a default here so that it satisfies the gods of strictNullChecks:

configOptions.get<string[]>('projectRootsSearchExclude') ?? []

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks. I used the default value signature of the get:

configOptions.get<string[]>('projectRootsSearchExclude', []) 

Does that also satisfy the rule? Less syntax to parse...

Copy link
Contributor

Choose a reason for hiding this comment

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

ooooh, I didn't know about that one! I think that should fix it? and If not I can fix it later when i'm fixing null check things 😊

@PEZ PEZ marked this pull request as ready for review March 21, 2022 08:20
@PEZ
Copy link
Collaborator Author

PEZ commented Mar 21, 2022

@Cyrik : can you have a look at e356cfd and see if you think it is viable way to deal with the quick-pick menus in e2e tests? I didn't figure out a very nice way to select the correct sequence...

I'd be awesome if @corasaurus-hex and @bpringe had a look as well.

❤️

@PEZ
Copy link
Collaborator Author

PEZ commented Mar 21, 2022

I wonder why that saveAs doesn't do the trick now... I'll have a closer look. Thanks!

Copy link
Contributor

@corasaurus-hex corasaurus-hex left a comment

Choose a reason for hiding this comment

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

I think this looks great! I love to see code improvements like this.

src/connector.ts Outdated
let projectDirUri = state.getProjectRootUri();
if (!projectDirUri) {
projectDirUri = await state.getOrCreateNonProjectRoot(context, true);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

it looks like getOrCreateNonProjectRoot calls getProjectRootUri internally, first thing, and returns it later. Could we ditch the getProjectRootUri here and just call getOrCreateNonProjectRoot on its own here? Or should we remove the getProjectRootUri from getOrCreateNonProjectRoot? Or just leave everything as-is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll have to check and think. You are probably right. This has been somewhat cleaned up, but I might have missed this opportunity. Tomorrow, though, because right now too 💤 !

src/connector.ts Outdated
if (!projectDirUri) {
projectDirUri = await state.getOrCreateNonProjectRoot(context, true);
}
await state.initProjectDir(projectDirUri);
Copy link
Contributor

Choose a reason for hiding this comment

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

We add a .catch to this function in connectCommand, do we need one here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Iirc i added the one in connectCommand because the user can do funny stuff with the menu. Here we don't allow that. But it could also go wrong because of non-validated glob patterns, so yes, we should have one here anyway. =)

src/utilities.ts Outdated
@@ -547,6 +558,7 @@ export {
logSuccess,
getCljsReplStartCode,
getShadowCljsReplStartCode,
quickPickActive as quicPickActive,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we get rid of the as quicPickActive here? We'll need to fix the references to it in the tests, too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No idea why this coercion is here... I'll ditch it!

@PEZ
Copy link
Collaborator Author

PEZ commented Mar 21, 2022

I love to see code improvements like this.

❤️

When I tried to extract the find-root-paths stuff to a module named project-root.ts, it turned out there was already such a module! And it had yet another implementation of the same traversing! Crazy. I just replaced it with the new stuff and updated the only call site. It seems to work. But also makes us glob more often, of course. Maybe we should keep the other way to find closest root around anyway...

docs/site/connect.md Outdated Show resolved Hide resolved
src/project-root.ts Outdated Show resolved Hide resolved
@PEZ PEZ merged commit 00abd8b into dev Mar 22, 2022
@PEZ PEZ deleted the 1254-multiple-project-roots branch March 22, 2022 16:48
@PEZ
Copy link
Collaborator Author

PEZ commented Mar 22, 2022

🎉

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.

4 participants