Kotlin unresolved reference to local package - kotlin

File ./Main.kt:
import numbers
fun main() {
var value = numbers.sum(7, 4)
}
File ./numbers/Operations.kt:
package numbers
fun sum(val1: Int, val2: Int): Int {
return val1 + val2
}
Running the command kotlinc Main.kt outputs:
Main.kt:1:8: error: unresolved reference: numbers
import numbers
Main.kt:4:17: error: unresolved reference: numbers
var value = numbers.sum(2, 3)
If I try to add import java (I am new in Kotlin ans I saw someone imported this. I thought it is a part of a standard library) then output also contains:
Main.kt:1:8: error: packages cannot be imported
import java
What I did wrong?
SOLUTION (Thanks to #gidds):
Was need to pass each file to the complier, not like with Java compiler (javac)
kotlinc Main.kt numbers/Operations.kt

numbers is a package.  And, as the error says, packages cannot be imported.  Only classes, functions, or properties.
If you import numbers.sum, you should find you can call it with e.g. sum(7, 4).
Or you could call its fully-qualified name directly, without the import: numbers.sum(7, 4).
It's the same with java, which is also a package.  You can import java.util.concurrent.ConcurrentHashMap (a class), but not java, java.util, nor java.util.concurrent (which are all packages).  (Java has the same restriction.)

Related

Can't compile Kotlin Jackson Extensions readValue(File)

I am trying to use Kotlin Jackson extensions to do JSON conversions in my code. But for some reason, I am getting a syntax error when trying to use the readValue(File) function.
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3'
---
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
...
private val objectMapper = jacksonObjectMapper()
...
val factionList: List<Faction> = objectMapper.readValue<List<Faction>>(
File(javaClass.classLoader.getResource("data/factions.json").file))
The error I get from the compiler is:
None of the following functions can be called with the arguments supplied.
readValue(JsonParser!, ResolvedType!)
...
[it lists all the valid function signatures ...]
However, none of the extension functions seem to be showing up in that list. If I click on the function and hit Cmd-B in IntelliJ, I am seeing the readValue(File) method in the extensions code.
I am confused why the function is not being found by the compiler.
You're most likely missing the following import:
import com.fasterxml.jackson.module.kotlin.readValue
Forgot this a few times myself.

Unable to reference kotlinx.cinterop package in Kotlin Multiplatform project

I created a Kotlin Multiplatform project based on the example for iOS and Android (https://kotlinlang.org/docs/tutorials/native/mpp-ios-android.html). Within my iOS target, I am using cinterop to link in a 3rd party Objective-C framework. This is working fine. I am able to reference the framework classes in my Kotlin code within the 'iosMain' source set. However, one of the method calls requires an NSError** parameter. I am attempting to use the following to create this variable in my Kotlin code:
kotlinx.cinterop.NativePlacement.allocPointerTo<kotlinx.cinterop.ObjCObjectVar<platform.Foundation.NSError?>()
I have not been able to find away around the following errors:
> Task :sharedLib:linkMainDebugFrameworkIOS FAILED
src/iosMain/kotlin/Platform.kt:9:50: error: unresolved reference: allocPointerTo
val error = kotlinx.cinterop.NativePlacement.allocPointerTo<kotlinx.cinterop.ObjCObjectVar<platform.Foundation.NSError?>()
^
src/iosMain/kotlin/Platform.kt:9:126: error: no value passed for parameter 'rawPtr'
val error = kotlinx.cinterop.NativePlacement.allocPointerTo<kotlinx.cinterop.ObjCObjectVar<platform.Foundation.NSError?>()
My understanding is that this package is part of stdlib, which should be added as a dependency automatically. Am I missing a piece of the equation somewhere?
UPDATE
The following is an example of passing an NSError* reference from Kotlin:
memScoped {
val errorRef = alloc<ObjCObjectVar<NSError?>>()
someObjCObject.method(errorRef.ptr)
}
kotlinx.cinterop.NativePlacement is an interface name, not a class name. You need an instance of the NativePlacement interface to work. For example memscoped{..} block will work, e.g.
import kotlinx.cinterop.*
import platform.Foundation.*
val p = memScoped {
allocPointerTo<ObjCObjectVar<NSError?>>()
}
The memscoped{..} accepts a lambda, inside the lambda the receiver implements the NativePlacement type, so there is no need for a qualifier to call a function on it
https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver

Is there a way to suppress Kotlin's default import?

Is there a way to suppress (e.g., via a commnad line flag passed to the compiler) Kotlin's default import of multiple packages? or - alternatively - to be selective about it?
This is easy, just use your alternative to replace it by using as, and the default import will be replaced by your one.
Here's a simple example, if you want to use java.lang.String instead of kotlin.String, although it's not recommended, this is just an example.
import java.lang.String as String
// here, String is not `kotlin.String`.
private fun main(vararg args: String) {
}
BTW there's a trick about refactoring, like if you want to replace all Any used in a file with java.lang.Object, put this after the package declaration:
import java.lang.Object as Any
And the implicit import to Any is suppressed and superseded by Object.

Extension function collision [duplicate]

If I have a jar, on the classpath, where I've created an extension function on say the String class for argument's sake and I have another jar with the same extension function on String, how will Kotlin resolve the two?
I presume if both functions are defined in the same packages then there will be a clash?
But if different packages, how I can distinguish the two extensions?
Indeed, if they're in the same package, it won't compile. For the other scenario, let's say you have two files with two different packages, containing extension functions with the same signature:
First file:
package ext1
fun Int.print() = print(this)
Second file:
package ext2
fun Int.print() = print(this * 2)
And this file where you're trying to use it:
package main
fun main(args: Array<String>) {
42.print()
}
IntelliJ will actually give you an import dialog where you can choose which one you want to use:
You can import one of them like this:
import ext1.print
And if you need to use the other one as well, you can rename it with the as keyword. This keyword works for imports in general, classes with the same name, etc.
import ext2.print as print2
So this program compiles and prints 4284:
package main
import ext1.print
import ext2.print as print2
fun main(args: Array<String>) {
42.print()
42.print2()
}
As a quick note, the one you import with the as keyword will be slightly harder to use, as autocomplete doesn't seem to pick it up well, selecting the second option here just completes the call to 42.print().
So since extension function in kotlin is just static function, other functions will be distinguish by import.
Also you can make alias for one of extension functions for more readability:
import by.bkug.extensions.helpers.extension
import by.bkug.extensions.extension as extension1
fun test() {
myType().extension() // by.bkug.extensions.helpers.extension
myType().extention1() // by.bkug.extensions.extension
}

Escape reserved words in an import

When using Java classes in Kotlin, sometimes they use identifiers that are reserved word in kotlin. The java interop documentation says you can use backtick (`) character but this doesn't work in imports. So how to escaped reserved words on import.
e.g. The tinkerpop library has a class called '__' but thats a Kotlin reserved so if I import it like below it gives an error.
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
I can import it using the wild card like this:
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.*
but because I only use the one class then Intellij's code formatter replaces it with the previous version of the import that gives an error. (Which I guess is a bug in the intellij formatter as well)
For the answers that suggest using backtick ` works. It does not. This does not compile even on try.kotlinlang.org.
Assuming a class exists defined as
package blah
class `__` {
}
This is what happens when you import it with backticks.
Disclaimer: I am not a Kotlin user.
The Kotlin Grammar page ( https://kotlinlang.org/docs/reference/grammar.html#SimpleName ) states that the import keyword is followed by a SimpleName ("." SimpleName) where SimpleName is defined as either <java identifier> or "``" <java identifier> "``"
According to the above rules, each component that needs escaping should be surrounded in single backtick characters. As only the last name is reserved your code should look like this:
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.`__`
I tried using this in an online Kotlin tool ( http://try.kotlinlang.org/ ) and the syntax was accepted.
Update
I created a 2-file program in try.kotlinlang.org and I can reproduce the problem, and fix it.
So the issue isn't just that keywords and other reserved words need to be escaped with backticks (though in this case, the name __ (two underscores) is not a keyword in Kotlin, but that Kotlin does not seem to allow reserved names to even exist in-scope!
Here's my test-case:
File1.kt
package blah
class `__` {
fun foo(): Int {
return 5
}
}
File2.kt
import blah.__
fun test2() {
val us = __()
us.foo
}
This gives me this compile-time error:
File2.kt - Error:(1,) Names _, , _, ..., are reserved in Kotlin
If I change File2.kt to this, then it works fine:
import blah.__ as underscore
fun test2() {
val us = underscore()
us.foo
}
Using backticks doesn't seem to help at all, but it does give me unexpected errors:
import blah.`__` as `__`
fun test2() {
val us = `__`() <-- error is here
us.foo()
}
File2.kt - Error: (4, 13) Unresolved reference: __
Variations of the names with backticks and unescaped double-underscores yields no effect.
So it seems the solution is to alias the name to something else during import.
One method I've found that works is to import it with an alias which is ok but it does change the name used in code.
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__ as underscore
As specified in the docs, your import must look like:
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.`__`
Then to use the underscore symbol in the code you'll have to escape it every time, so an alias is the best solution:
`__`.foo()
Docs: https://kotlinlang.org/docs/reference/java-interop.html#escaping-for-java-identifiers-that-are-keywords-in-kotlin