Skip to content

Track build file changes#168

Merged
milesziemer merged 2 commits intosmithy-lang:mainfrom
milesziemer:track-build-file-changes
Nov 5, 2024
Merged

Track build file changes#168
milesziemer merged 2 commits intosmithy-lang:mainfrom
milesziemer:track-build-file-changes

Conversation

@milesziemer
Copy link
Copy Markdown
Contributor

This change makes the server register for document lifecycle events like
didChange for build files. Previous behavior was to register for file
system change events for build files, but eventually we want to give
diagnostics, completions, etc. for build files as you type, so we need
to track all changes. This change keeps existing behavior from the
user's perspective, as we still only reload projects on save, so it
serves mostly as a refactor.

I also extracted the state managed by SmithyLanguageServer to its own
class, ServerState, and flattened ProjectManager into that class, so we
can manage the state of the server in a more centralized location.

Depends on #167

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@milesziemer milesziemer force-pushed the track-build-file-changes branch from 019c186 to 0402ac4 Compare October 10, 2024 16:53
This change makes the server register for document lifecycle events like
didChange for build files. Previous behavior was to register for file
system change events for build files, but eventually we want to give
diagnostics, completions, etc. for build files as you type, so we need
to track all changes. This change keeps existing behavior from the
user's perspective, as we still only reload projects on save, so it
serves mostly as a refactor.

I also extracted the state managed by SmithyLanguageServer to its own
class, ServerState, and flattened ProjectManager into that class, so we
can manage the state of the server in a more centralized location.
@milesziemer milesziemer force-pushed the track-build-file-changes branch from 0402ac4 to 9f1e92b Compare October 28, 2024 20:54
@milesziemer milesziemer marked this pull request as ready for review October 28, 2024 20:54
@milesziemer milesziemer requested a review from a team as a code owner October 28, 2024 20:54
@milesziemer milesziemer requested review from hpmellema and kstich and removed request for kstich October 28, 2024 20:54
Comment thread src/main/java/software/amazon/smithy/lsp/project/ProjectConfig.java Outdated
Comment thread src/main/java/software/amazon/smithy/lsp/SmithyLanguageServer.java
for (Project project : attachedProjects.values()) {
ProjectFile projectFile = project.getProjectFile(path);
if (projectFile != null) {
detachedProjects.remove(uri);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Im a little confused why we remove it from detached projects here? I would have thought that would get checked correctly in the isDetached below?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yea it does, but I'm not calling that method here. I think I meant to end up removing isDetached, but it ended up being too useful. I did some refactoring and pulled the removal logic into the new findAttachedAndRemoveDetached

Comment thread src/main/java/software/amazon/smithy/lsp/ServerState.java Outdated
@milesziemer milesziemer merged commit 3b1ea23 into smithy-lang:main Nov 5, 2024
yasmewad pushed a commit to yasmewad/smithy-language-server that referenced this pull request Nov 5, 2024
This change makes the server register for document lifecycle events like
didChange for build files. Previous behavior was to register for file
system change events for build files, but eventually we want to give
diagnostics, completions, etc. for build files as you type, so we need
to track all changes. This change keeps existing behavior from the
user's perspective, as we still only reload projects on save, so it
serves mostly as a refactor.

I also extracted the state managed by SmithyLanguageServer to its own
class, ServerState, and flattened ProjectManager into that class, so we
can manage the state of the server in a more centralized location.
milesziemer added a commit to milesziemer/smithy-language-server that referenced this pull request Nov 6, 2024
Fixes a bug in smithy-lang#168 where the server would send the wrong registration
for didSave on Smithy files.
milesziemer added a commit that referenced this pull request Nov 6, 2024
Fixes a bug in #168 where the server would send the wrong registration
for didSave on Smithy files.
milesziemer added a commit to milesziemer/smithy-language-server that referenced this pull request Feb 14, 2025
smithy-lang#168 started
tracking build file changes via lifecycle methods, didOpen, etc. But it
didn't make a distinction between what was a build file, and what was a
Smithy file. There are two paths didOpen can take - the first is when
the file being opened is known to be part of a project. In this case,
the file is already tracked by its owning Project, so its basically a
no-op. The second path is when the file does not belong to any project,
in which case we created a "detached" project, which is a project with
no build files and just a single Smithy file. So if you opened a build
file that wasn't known to be part of a Project, the language server
tried to make a detached project containing the build file _as a smithy
file_. This is obviously wrong, but wasn't observable to clients AFAICT
because clients weren't set up to send requests to the server for build
files (specifically, you wouldn't get diagnostics or anything, only for
.smithy files). However, recent commits, including
smithy-lang#188, now want
to provide language support for smithy-build.json. In testing these new
commits with local changes to have VSCode send requests for
smithy-build.json, the issue could be observed. Specifically, the issue
happens when you open a new smithy-build.json before we receive the
didChangeWatchedFiles notification that tells us a new build file was
created. didChangeWatchedFiles is the way we actually updated the state
of projects to include new build files, or create new Projects. Since we
can receive didOpen for a build file before didChangeWatchedFiles, we
needed to do something with the build file on didOpen.

This commit addresses the problem by adding a new Project type,
`UNRESOLVED`, which is a project containing a single build file that no
existing projects are aware of. We do this by modifying the didOpen path
when the file isn't known to any project, checking if it is a build file
using a PathMatcher, and if it is, creating an unresolved project for
it. Then, when we load projects following a didChangeWatchedFiles, we
just drop any unresolved projects with the same path as any of the build
files in the newly loaded projects (see ServerState::resolveProjects).

I also made some (upgrades?) to FilePatterns to better handle the
discrepancy between matching behavior of PathMatchers and clients
(see smithy-lang#191).
Now there are (private) `*PatternOptions` enums that FilePatterns uses to
configure the pattern for different use cases. For example, the new
FilePatterns::getSmithyFileWatchPathMatchers provides a list of
PathMatchers which should match the same paths as the _watcher_ patterns
we send back to clients, which is useful for testing.
milesziemer added a commit that referenced this pull request Feb 14, 2025
#168 started
tracking build file changes via lifecycle methods, didOpen, etc. But it
didn't make a distinction between what was a build file, and what was a
Smithy file. There are two paths didOpen can take - the first is when
the file being opened is known to be part of a project. In this case,
the file is already tracked by its owning Project, so its basically a
no-op. The second path is when the file does not belong to any project,
in which case we created a "detached" project, which is a project with
no build files and just a single Smithy file. So if you opened a build
file that wasn't known to be part of a Project, the language server
tried to make a detached project containing the build file as a smithy
file. This is obviously wrong, but wasn't observable to clients AFAICT
because clients weren't set up to send requests to the server for build
files (specifically, you wouldn't get diagnostics or anything, only for
.smithy files). However, recent commits, including
#188, now want
to provide language support for smithy-build.json. In testing these new
commits with local changes to have VSCode send requests for
smithy-build.json, the issue could be observed. Specifically, the issue
happens when you open a new smithy-build.json before we receive the
didChangeWatchedFiles notification that tells us a new build file was
created. didChangeWatchedFiles is the way we actually updated the state
of projects to include new build files, or create new Projects. Since we
can receive didOpen for a build file before didChangeWatchedFiles, we
needed to do something with the build file on didOpen.

This commit addresses the problem by adding a new Project type,
UNRESOLVED, which is a project containing a single build file that no
existing projects are aware of. We do this by modifying the didOpen path
when the file isn't known to any project, checking if it is a build file
using a PathMatcher, and if it is, creating an unresolved project for
it. Then, when we load projects following a didChangeWatchedFiles, we
just drop any unresolved projects with the same path as any of the build
files in the newly loaded projects (see ServerState::resolveProjects).

I also made some (upgrades?) to FilePatterns to better handle the
discrepancy between matching behavior of PathMatchers and clients
(see #191).
Now there are (private) *PatternOptions enums that FilePatterns uses to
configure the pattern for different use cases. For example, the new
FilePatterns::getSmithyFileWatchPathMatchers provides a list of
PathMatchers which should match the same paths as the watcher patterns
we send back to clients, which is useful for testing.

I also fixed an issue where parsing an empty build file would cause an NPE
when trying to map validation events to ranges. Document::rangeBetween
would return null if the document was empty, but I wasn't checking for that
in ToSmithyNode (which creates parse events).

The reason the range is null is because Document.lineOfIndex returns
oob for an index of 0 into an empty document. Makes sense, as an empty
document has no lines. I updated a DocumentTest to clarify this
behavior.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
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.

2 participants