Java Interop / IntelliJ: Property syntax for method invocations


#1

Say you have the following Java class:

public class MyClass
{
    private String name = "";

    public String getName()
    {
        return name;
    }
}

Then you can do the following in Kotlin:

println(MyClass().getName())

However, IntelliJ recognizes the prefix get and will suggest you use property notation:

println(MyClass().name)

Furthermore, IntelliJ offers code completion for the latter option only

So far, this is great: name is a property and should be accessed like one, using the concise syntax.

This becomes a problem when there is a Java method with prefix get that is actually not a property. Sometimes, the line between methods and properties may be blurry, but sometimes it is quite clear. E.g., javax.persistence.Query.getResultList() is clearly a method:

  1. It would be strange to think of a result as a “property” of a query.
  2. An invocation may returns a different instance each time.
  3. The method may hit the database.

So, writing query.resultList would actually be misleading and masquerading a potentially expensive method call. It is better to write query.getResultList(), but IntelliJ will discourage you to do so.

The ideal solution to this problem would involve a new annotation @NoProperty that gets added to all Java methods like Query.getResultList(). Since this is not going to happen, I suggest that IntelliJ should allow you to configure get-prefixed methods that are supposed to be called like methods. A default list could be community-curated. It is very unlikely that there will be versioning issues. Another option could be bytecode analysis to find out whether get-prefixed methods ultimately only access fields (possibly via a chain of get-prefixed methods). If so, they are properties, otherwise the are not.

For background information, you might want to check out the guide on properties vs. methods in .NET.

Update:

The Kotlin reference also has a small section on functions vs. properties, giving basically the same advice as the .NET guide:

In some cases functions with no arguments might be interchangeable with read-only properties. Although the semantics are similar, there are some stylistic conventions on when to prefer one to another.

Prefer a property over a function when the underlying algorithm:

- does not throw any Exceptions
- has a O(1) complexity
- is cheap to calculate (or caсhed on the first run)
- returns the same result over invocations

#2

IntelliJ IDEA already offers this configuration possibility.


#3

Indeed that looks exactly like what I have been searching for. Unfortunately, I just cannot seem to be able to persist my changes to that list of excluded methods.

Works: When I navigate to that option from the settings menu and disable the rule (in profile “Default IDE”), the “Apply” button becomes enabled, as expected. If I click “OK”, the window closes and the rule is now disabled, as expected. If I reopen the settings, it is still disabled, as expected.

Does not work: When I add a method to the list, the “Apply” button stays disabled. If I close the window, the method is not excluded by the rule. If I reopen the settings, the new method is gone. This looks like a bug to me. Should I create an issue in your tracker?

IntelliJ IDEA 2017.2.4
Build #IC-172.4155.36, built on September 11, 2017
JRE: 1.8.0_152-release-915-b11 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 7 6.1


#4

See: https://youtrack.jetbrains.com/issue/IDEA-180362