-
Notifications
You must be signed in to change notification settings - Fork 231
General override member(s) functionality #379
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, a few style suggestions here and there, but nothing too major 👍
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection | ||
|
||
// TODO: see where this should ideally be placed | ||
private const val DEFAULT_TAB_SIZE = 4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We currently hardcode this in the formatter too, I think there was an open issue to make this configurable, but that's probably out-of-scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. That's a great point. I can't find the exact issue, but I suggest we do this as part of another PR. Like you said, that is a bit out of scope for this PR... I prefer to keep the PRs as to-the-point as possible, which helps me keep focus on each task. 🙂 Please link the issue if you find it 🙂
fun listOverridableMembers(file: CompiledFile, cursor: Int): List<CodeAction> { | ||
val kotlinClass = file.parseAtPoint(cursor) | ||
|
||
if (kotlinClass is KtClass) { | ||
return createOverrideAlternatives(file, kotlinClass) | ||
} | ||
|
||
return emptyList() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can rewrite this to be a bit more concise
fun listOverridableMembers(file: CompiledFile, cursor: Int): List<CodeAction> { | |
val kotlinClass = file.parseAtPoint(cursor) | |
if (kotlinClass is KtClass) { | |
return createOverrideAlternatives(file, kotlinClass) | |
} | |
return emptyList() | |
} | |
fun listOverridableMembers(file: CompiledFile, cursor: Int): List<CodeAction> = | |
when (file.parseAtPoint(cursor)) { | |
is KtClass -> createOverrideAlternatives(file, kotlinClass) | |
else -> emptyList() | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could in theory rewrite this to use a when-expression like above (with modifications), but we need the kotlinClass
-reference for the createOverrideAlternatives
-call. That means the suggestion above won't compile due to unknown reference to kotlinClass
. If we still need that variable, I don't think it improves much just using a when-expression instead of the if-version. Feel free to disagree 🙂 (or tell me if I'm missing something!)
server/src/main/kotlin/org/javacs/kt/overridemembers/OverrideMembers.kt
Outdated
Show resolved
Hide resolved
server/src/main/kotlin/org/javacs/kt/overridemembers/OverrideMembers.kt
Outdated
Show resolved
Hide resolved
server/src/main/kotlin/org/javacs/kt/overridemembers/OverrideMembers.kt
Outdated
Show resolved
Hide resolved
// Checks if two functions have matching parameters | ||
private fun parametersMatch( | ||
function: KtNamedFunction, | ||
functionDescriptor: FunctionDescriptor | ||
): Boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we could rewrite this into a big functional zip
? I haven't checked on the specifics though, maybe there's too much specialized logic to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit unsure about this. We loop through two different lists; value parameters and type parameters. Unsure on how much it would improve in this case, but I may miss something...
@fwcd , do you have time to look at this again soon? Would be good to get it done while the details are still semi-fresh in my memory. Sorry for nagging, know you are probably busy 🙁 |
@fwcd , bump? |
Lgtm, sorry for the delay. Thanks! |
@fwcd , no problem 🙂 Sorry for nagging you. Just very eager about this project, so I can get a little impatient 🙁 |
General info
Override any member that is currently not implemented in the current class. This includes open functions, functions with default implementations, open members, abstract stuff etc. The main difference here is that this is general override member functionality, NOT JUST abstract members like the quick fix does. This is super useful for cases where you need to override a default implementation (e.g toString, Thread run, lsp4j interface methods like in TextDocumentService etc.), NOT just the unimplemented abstract ones. For me it would be super useful for my day job using Kotlin 😄 Having to google api docs to find signatures are a pain in the ass just for doing simple stuff like this.
Two small issues:
I think these are very minor. Just having this functionality in place would at least make me more productive using the language server 😄
The quick fix for abstract methods and this new functionality, share a lot of code. I've moved most of the code to the override-package, as that was the most logical place to put it.
Fixes #359
This is a new protocol extension, so each lsp-client will need to have an implementation to use it. I've only done one for Emacs so far, and speaking of...
Emacs screenshots
Running lsp-kotlin-override-members on MyClass (notice that multiple selections are possible!):

When we click enter:

(yes, it is the same sample project I often use for screenshot. A boring Spring Boot demo app)
Yes, it works for external interfaces and open classes as well, don't worry 🙂 There is an example of JDK Thread in the tests (in this PR, not in Emacs)
Emacs client implementation (lsp-mode):
https://github.com/themkat/lsp-mode/blob/kotlin_overrides/clients/lsp-kotlin.el#L224
Will make a PR for it once this PR has been merged. Just in case something changes.
Will see if I can find the time to make a VSCode version or not. If not, I will make an issue in the vscode-kotlin repo with enough details to get someone else started🙂 Really want to work on either Type hierarchy or Javadoc for Kotlin SDK and the JDK instead 😛EDIT: Made a VSCode version, as I was bored after work yesterday: fwcd/vscode-kotlin#104