Skip to content

Fix #5895: REPL autocompletion crashes in certain cases #6414

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

Merged
merged 1 commit into from
May 3, 2019

Conversation

anatoliykmetyuk
Copy link
Contributor

Crashes

The crashes happen due to the fact that in certain cases,
certain trees get mispositioned during code completion. E.g.
this happens with opaque type T = Int or object Foo { type T = Int.
The tree spans are set incorrectly because repl doesn't set the
sources of these trees correctly. Precisely, when typechecking
on code completion, a virtual source is used. However, when
parsing for autocompletion, a line source is used which is
created by the parsing logic. This commit makes sure that REPL
is consistent in its source choices when computing code completions.

Completion

The above commit does not bring the code completion for opaque types, however.

REPL code completion computes completion candidates for a given
expression after typechecking it. Typechecking opaque types
desugars them from <mods> type T = Int to <mods> type T = T.T.
The completion relies on the position of the user's cursor
in the input expression to know what part of this expression to complete.
Since the cursor does not take the semantic info computed by typechecking,
the cursor points to T.T and not to Int on completion request.
Completion on synthetic T.T does not pick any candidates, which is
unexpected to the user. The expected behavior is to complete on Int,
the underlying type. This commit achieves the expected behavior by
making sure opaque types are treated as ordinary types on code completion.

@anatoliykmetyuk anatoliykmetyuk changed the title Fix #5895: REPL autocompletion crushes in certain cases Fix #5895: REPL autocompletion crashes in certain cases May 1, 2019
@anatoliykmetyuk
Copy link
Contributor Author

The corner case where this solution misbehaves:

opaque type T = String; val x: T = ???; x.len<TAB>

The above will autocomplete to length, though shouldn't. The below will also autocomplete:

scala> object Foo {
     |   opaque type T = String
     |   val x: T = ???
     |   x.len<TAB>

If evaluated, the behaviour is correct:

scala> object Foo {
     |   opaque type T = String
     |   val x: T = ???
     |   x.length
     | }
4 |  x.length
  |  ^^^^^^^^
  |  value length is not a member of Foo.T

An alternative approach would be to map the cursor position to the trees generated after desugaring and typecheck. However, FTTB it seems the cursor is oblivious to the transformations done to the input and depends only on the input string.

@smarter
Copy link
Member

smarter commented May 1, 2019

 |   x.len<TAB>

Don't know what's going on but at this point we should be looking at the type of x which should be T, and then getting the members of T, since T is opaque this shouldn't return length.

@anatoliykmetyuk
Copy link
Contributor Author

Ok, I removed the completion part but left the crash part since it affects not only opaque types (see the test). Hope you don't mind a bit of FP inside :) I've also created an issue #6415 to log the problem with opaque types completion.

@anatoliykmetyuk anatoliykmetyuk requested review from nicolasstucki and smarter and removed request for nicolasstucki May 1, 2019 15:24
Copy link
Contributor

@nicolasstucki nicolasstucki left a comment

Choose a reason for hiding this comment

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

Otherwise LGTM

Given that we have #6415 to fix the completion itself

The crashes happen due to the fact that in certain cases,
certain trees get mispositioned during code completion. E.g.
this happens with `opaque type T = Int` or `object Foo { type T = Int`.
The tree spans are set incorrectly because repl doesn't set the
sources of these trees correctly. Precisely, when typechecking
on code completion, a virtual source is used. However, when
parsing for autocompletion, a line source is used which is
created by the parsing logic. This commit makes sure that REPL
is consistent in its source choices when computing code completions.
@anatoliykmetyuk anatoliykmetyuk merged commit a7dbb6c into scala:master May 3, 2019
@anatoliykmetyuk anatoliykmetyuk deleted the i5895 branch May 3, 2019 08:48
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.

3 participants