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

[READY] Allow switching to a different JavaScript project with RestartServer #875

Merged

Conversation

micbou
Copy link
Collaborator

@micbou micbou commented Nov 20, 2017

Contrarily to what the YCM docs say, issuing the :YcmCompleter RestartServer command to switch to a different JavaScript project doesn't work. The reason is that we don't set the working directory when starting the Tern server. Same issue if the user starts the client outside a project and then open a file in that project. It's even worse in that case because no warning will be displayed to the user.

I considered passing the request_data object when initializing the completer but that doesn't work because the request is not always available. I also considered adding support for multiple projects similarly to what the C# completer does but I felt it was too much work. Finally, I went for starting the server on the FileReadyToParse event.


This change is Reviewable

@codecov-io
Copy link

codecov-io commented Nov 20, 2017

Codecov Report

Merging #875 into master will increase coverage by 0.19%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master     #875      +/-   ##
==========================================
+ Coverage   94.81%   95.01%   +0.19%     
==========================================
  Files          79       79              
  Lines        5440     5455      +15     
  Branches      171      171              
==========================================
+ Hits         5158     5183      +25     
+ Misses        233      225       -8     
+ Partials       49       47       -2

@micbou micbou changed the title [READY] Allow switching to a different JavaScript project with RestartServer [WIP] Allow switching to a different JavaScript project with RestartServer Nov 22, 2017
@micbou micbou force-pushed the switch-javascript-project-restart-server branch 2 times, most recently from bb33265 to 727d162 Compare November 23, 2017 22:59
Start Tern on the FileReadyToParse event. Make sure there is only one attempt
to start the server. Add Tern configuration path to debugging information.
@micbou micbou force-pushed the switch-javascript-project-restart-server branch from 727d162 to e587501 Compare November 24, 2017 19:15
@micbou micbou changed the title [WIP] Allow switching to a different JavaScript project with RestartServer [READY] Allow switching to a different JavaScript project with RestartServer Nov 24, 2017
@micbou
Copy link
Collaborator Author

micbou commented Nov 24, 2017

I did some refactoring in the tests by introducing an utility function to start the Tern server. Also, similarly to the recent changes in PR #857, I slightly changed the logic so that we only try to start the Tern server once. PR is ready.


Reviewed 6 of 6 files at r1, 4 of 4 files at r2, 1 of 1 files at r3, 1 of 1 files at r4.
Review status: all files reviewed at latest revision, all discussions resolved.


Comments from Reviewable

@bstaletic
Copy link
Collaborator

Makes me wonder if we should start all semantic completers on FileReadyToParse.
:lgtm:


Reviewed 2 of 6 files at r1, 3 of 4 files at r2, 1 of 1 files at r4.
Review status: all files reviewed at latest revision, all discussions resolved.


Comments from Reviewable

@Valloric
Copy link
Member

:lgtm:

Thanks!


Review status: all files reviewed at latest revision, 1 unresolved discussion.


ycmd/completers/javascript/tern_completer.py, line 391 at r4 (raw file):

      _logger.info( 'Starting Tern server...' )

      filepath = request_data[ 'filepath' ]

This PR adds 10+ lines of code to a function with a TODO of "this function is too long". :(

Doesn't block this PR, but we should consider refactoring this sooner rather than later.


Comments from Reviewable

@bstaletic
Copy link
Collaborator

Doesn't block this PR, but we should consider refactoring this sooner rather than later.

So is it time to merge this?


Review status: all files reviewed at latest revision, 1 unresolved discussion, all commit checks successful.


Comments from Reviewable

@micbou
Copy link
Collaborator Author

micbou commented Nov 27, 2017

Reviewed 1 of 1 files at r5.
Review status: all files reviewed at latest revision, 2 unresolved discussions.


ycmd/completers/javascript/tern_completer.py, line 391 at r4 (raw file):

Previously, Valloric (Val Markovic) wrote…

This PR adds 10+ lines of code to a function with a TODO of "this function is too long". :(

Doesn't block this PR, but we should consider refactoring this sooner rather than later.

Did some simplifications and moved the new code to a separate function. It's now 54 lines instead of 74.


ycmd/completers/javascript/tern_completer.py, line 442 at r4 (raw file):

      except Exception:
        _logger.exception( 'Unable to start Tern server' )
        self._CleanUp()

Removed this try/except block as it was unlikely to ever catch something (CreateLogFile, OpenForStdHandle, and SafePopen are never supposed to fail).


Comments from Reviewable

@puremourning
Copy link
Member

Review status: all files reviewed at latest revision, 8 unresolved discussions.


ycmd/completers/javascript/tern_completer.py, line 157 at r5 (raw file):

    if not FindTernProjectFile( filepath ):
      raise RuntimeError( 'Warning: Unable to detect a .tern-project file '
                          'in the hierarchy before ' + filepath +

should this be a dir name rather than file name? totally optional. i'm ambivalent.


ycmd/completers/javascript/tern_completer.py, line 268 at r5 (raw file):

    with self._server_state_mutex:
      extras = [
        responses.DebugInfoItem( key = 'configuration file',

should we call it "Tern project file", as that is a little clearer that it is specific to Tern rather than YCM ? I theory at least editors and ycmd itself might have "configuration files". Again, optional.


ycmd/completers/javascript/tern_completer.py, line 386 at r5 (raw file):

    if not self._server_project_file:
      _logger.warning( 'No .tern-project file detected: %s', filepath )
      self._server_working_dir = os.path.dirname( filepath )

I think this might be a slight regression, but I'm not sure.

Previously in this scenario we would use Vim's working dir, which might turn out a better choice than the file's directory.

Example might be:

  • a user is used to using the javascript completion without a tern project file
  • they typically cd /some/path
  • the structure is like /some/path/lib_one/*.js, /some/path/lib_two/*.js
  • they use vim lib_one/file.js, which contains var x = require( 'lib_two/another_file.js' )

I don't know for certain if this would or would not have previously just about worked based on the wd of the term server being /some/path. But I'm pretty sure that it wouldn't with the wd of /some/path/lib_one.

I guess the key question for discussion is: if we can't find a tern project file, should we really use the dirname of the file, or revert to the previous behaviour of using the WD of the client. I suspect that we should do the latter, for safety unless there's a good reason not to... or I totally missed the point, which is of course also possible!


ycmd/completers/javascript/tern_completer.py, line 442 at r5 (raw file):

      if self._ServerIsRunning():
        _logger.info( 'Tern Server started with pid: %s listening on port %s',

should these be %d ? just being pedantic, you can ignore.


ycmd/completers/javascript/tern_completer.py, line 489 at r5 (raw file):

    self._server_started = False
    self._server_working_dir = None
    self._server_project_file = None

should we reset do_tern_project_check here ? I think it's not a new issue, but after restarting the server in some other directory, we probably want to re-scan for the tern project, and also re-warn for the "new" project.


ycmd/tests/javascript/event_notification_test.py, line 160 at r5 (raw file):

  # Finally, restart the server in a folder containing a .tern-project file. We
  # expect no error in that case.

should we test that if we restart it in some other directory (which doesn't have a .tern-project) that we do get another error (as mentioned, I think we don't, but i'm not 100% sure).


Comments from Reviewable

@micbou
Copy link
Collaborator Author

micbou commented Nov 28, 2017

Reviewed 1 of 1 files at r6.
Review status: all files reviewed at latest revision, 7 unresolved discussions.


ycmd/completers/javascript/tern_completer.py, line 157 at r5 (raw file):

Previously, puremourning (Ben Jackson) wrote…

should this be a dir name rather than file name? totally optional. i'm ambivalent.

It's simpler to put the filepath here.


ycmd/completers/javascript/tern_completer.py, line 268 at r5 (raw file):

Previously, puremourning (Ben Jackson) wrote…

should we call it "Tern project file", as that is a little clearer that it is specific to Tern rather than YCM ? I theory at least editors and ycmd itself might have "configuration files". Again, optional.

No need because this item is added in the extras field of the Tern DebugInfoServer object. It will appear as Tern configuration file in the output of :YcmDebugInfo.


ycmd/completers/javascript/tern_completer.py, line 386 at r5 (raw file):

Previously, puremourning (Ben Jackson) wrote…

I think this might be a slight regression, but I'm not sure.

Previously in this scenario we would use Vim's working dir, which might turn out a better choice than the file's directory.

Example might be:

  • a user is used to using the javascript completion without a tern project file
  • they typically cd /some/path
  • the structure is like /some/path/lib_one/*.js, /some/path/lib_two/*.js
  • they use vim lib_one/file.js, which contains var x = require( 'lib_two/another_file.js' )

I don't know for certain if this would or would not have previously just about worked based on the wd of the term server being /some/path. But I'm pretty sure that it wouldn't with the wd of /some/path/lib_one.

I guess the key question for discussion is: if we can't find a tern project file, should we really use the dirname of the file, or revert to the previous behaviour of using the WD of the client. I suspect that we should do the latter, for safety unless there's a good reason not to... or I totally missed the point, which is of course also possible!

I did some tests and Tern doesn't seem to rely at all on the working directory to resolve modules path (I tried with /tmp as the working directory and it works) so I don't think it matters. By the way, how's your example supposed to work without a .tern-project or .tern-config file (the node plugin is needed for module resolution)?


ycmd/completers/javascript/tern_completer.py, line 442 at r5 (raw file):

Previously, puremourning (Ben Jackson) wrote…

should these be %d ? just being pedantic, you can ignore.

Done.


ycmd/completers/javascript/tern_completer.py, line 489 at r5 (raw file):

Previously, puremourning (Ben Jackson) wrote…

should we reset do_tern_project_check here ? I think it's not a new issue, but after restarting the server in some other directory, we probably want to re-scan for the tern project, and also re-warn for the "new" project.

When restarting the server, the do_tern_project_check variable is set to True so we are going to warn the user again if there is no configuration file. However, this doesn't hurt to reset the variable here.


ycmd/tests/javascript/event_notification_test.py, line 160 at r5 (raw file):
This is tested just above:

Restart the server and check that it raises it again.


Comments from Reviewable

@puremourning
Copy link
Member

:lgtm:


Reviewed 2 of 6 files at r1, 3 of 4 files at r2, 1 of 1 files at r5.
Review status: 4 of 6 files reviewed at latest revision, 1 unresolved discussion.


ycmd/completers/javascript/tern_completer.py, line 386 at r5 (raw file):

Previously, micbou wrote…

I did some tests and Tern doesn't seem to rely at all on the working directory to resolve modules path (I tried with /tmp as the working directory and it works) so I don't think it matters. By the way, how's your example supposed to work without a .tern-project or .tern-config file (the node plugin is needed for module resolution)?

Like i said i wasn't sure if it would work before, or if there are other Tern behaviours that use relative paths in some sense.

I should have said "something like require( 'lib_two/....' )" .

Thanks for testing anyway, let's assume this is grand. In any event the solution is to add a .tern-project.


ycmd/completers/javascript/tern_completer.py, line 489 at r5 (raw file):

Previously, micbou wrote…

When restarting the server, the do_tern_project_check variable is set to True so we are going to warn the user again if there is no configuration file. However, this doesn't hurt to reset the variable here.

Great, thanks.


ycmd/tests/javascript/event_notification_test.py, line 160 at r5 (raw file):

Previously, micbou wrote…

This is tested just above:

Restart the server and check that it raises it again.

Heh ok sorry :)


Comments from Reviewable

@puremourning
Copy link
Member

Reviewed 2 of 2 files at r7.
Review status: all files reviewed at latest revision, 4 unresolved discussions.


Comments from Reviewable

@micbou
Copy link
Collaborator Author

micbou commented Nov 28, 2017

Let's merge.

@zzbot r+


Reviewed 2 of 2 files at r7.
Review status: all files reviewed at latest revision, 4 unresolved discussions.


Comments from Reviewable

@zzbot
Copy link
Contributor

zzbot commented Nov 28, 2017

📌 Commit 4ebb5da has been approved by micbou

@zzbot
Copy link
Contributor

zzbot commented Nov 28, 2017

⌛ Testing commit 4ebb5da with merge 58ccfde...

zzbot added a commit that referenced this pull request Nov 28, 2017
… r=micbou

[READY] Allow switching to a different JavaScript project with RestartServer

Contrarily to what the YCM docs say, issuing the `:YcmCompleter RestartServer` command to switch to a different JavaScript project doesn't work. The reason is that we don't set the working directory when starting the Tern server. Same issue if the user starts the client outside a project and then open a file in that project. It's even worse in that case because no warning will be displayed to the user.

I considered passing the `request_data` object when initializing the completer but that doesn't work because the request is not always available. I also considered adding support for multiple projects similarly to what the C# completer does but I felt it was too much work. Finally, I went for starting the server on the `FileReadyToParse` event.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/ycmd/875)
<!-- Reviewable:end -->
@zzbot
Copy link
Contributor

zzbot commented Nov 29, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: micbou
Pushing 58ccfde to master...

@zzbot zzbot merged commit 4ebb5da into ycm-core:master Nov 29, 2017
zzbot added a commit to ycm-core/YouCompleteMe that referenced this pull request Dec 3, 2017
[READY] Update ycmd

Include the following changes:
 - PR ycm-core/ycmd#856: update JediHTTP;
 - PR ycm-core/ycmd#860: improve diagnostics location in C-family languages;
 - PR ycm-core/ycmd#865: use Objective-C triggers for Objective-C++;
 - PR ycm-core/ycmd#869: support TypeScript 2.6.1;
 - PR ycm-core/ycmd#875: allow switching to a different JavaScript project with `RestartServer`;
 - PR ycm-core/ycmd#877: support `-idirafter` include flag in C-family languages.

Update the JavaScript documentation on how to switch to a different project. We only mention the `:YcmCompleter RestartServer` way as other methods involve restarting ycmd and losing all its data like stored identifiers.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2839)
<!-- Reviewable:end -->
snakeleon added a commit to snakeleon/YouCompleteMe-x64 that referenced this pull request Dec 4, 2017
Include the following changes:
 - PR ycm-core/ycmd#856: update JediHTTP;
 - PR ycm-core/ycmd#860: improve diagnostics location in C-family languages;
 - PR ycm-core/ycmd#865: use Objective-C triggers for Objective-C++;
 - PR ycm-core/ycmd#869: support TypeScript 2.6.1;
 - PR ycm-core/ycmd#875: allow switching to a different JavaScript project with `RestartServer`;
 - PR ycm-core/ycmd#877: support `-idirafter` include flag in C-family languages.
@micbou micbou deleted the switch-javascript-project-restart-server branch December 26, 2017 11:44
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.

6 participants