Skip to content

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