Skip to content

Add proper signatureHelp for unapply methods #15203

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 8 commits into from
May 19, 2022

Conversation

rochala
Copy link
Contributor

@rochala rochala commented May 17, 2022

SignatureHelp is used in LSP to provide help when applying or unapplying.
The real value is displaying each parameter name, type and documentation to make it easier to understand and use given method.
Currently dotty signatureHelp allowed to easily show unapply signatures but with 2 problems:

  • types were not inferred
  • returned signature provided too much clutter and wasn't useful.

It was caused by returning signature of unapply method, not its return type.
This implementation makes signatureHelp useful.

Example:

case class Foo[A, B](a: A, b: B)

val x = Foo(1, "")
x match {
  case Foo(x, @@) => ???
  case _ => ???
}

Previously:

unapply[A,B](x$0: Foo[A,B]): Foo[A, B]

After changes:

(a: Int, b: String)

Provided tests checks all supported syntax for unapply available in Scala3. They were created according to https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html

Returned value contains parameter names only when result is a case class, only then we are certain that unapply patterns match its apply method ( there is also check if unapply is synthetic to check for possible overrides ).

SIgnature help for unapply doesn't show values for tuples as they act as clutter.

There are possible peformance optimizations to be made in places where i left comments in this PR, but I can't find better way to do it without changing existing API.

Fixes #15126

@rochala rochala requested a review from tgodzik May 17, 2022 13:16
patterns: List[tpd.Tree]
)(using Context): (Int, Int, List[SingleDenotation]) =
val patternPosition = patterns.indexWhere(_.span.contains(span))
val activeParameter = extractParamTypess(fun.tpe.finalResultType.widen).headOption.map { params =>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Possible performance optimization as this is computed twice. We need to find number of parameters we can unapply to but i can't pass it without changing the API

Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

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

Looks good! I just have one small comment

List(productAccessors.map(_.info.finalResultType).toList)
else
ref.symbol.primaryConstructor.paramInfo.paramInfoss
case AppliedType(TypeRef(_, cls), (appliedType @ AppliedType(tycon, args)) :: Nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you able to add examples to each case to say in which situation each is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I managed to simplify this logic and added comments why each case is necessary for proper handling

Copy link
Contributor

Choose a reason for hiding this comment

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

awesome, thanks!

@rochala rochala merged commit d13b7a7 into scala:main May 19, 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.

Show proper unapply signature help
2 participants