Kotlin find all hardcoded strings in code using Android Studio - kotlin

(Ctrl+Alt+Shift+I) and type Hardcoded Strings: only find the hardcoded strings in the .java files and not find strings in .kt files

Ah, well actually there's an update. Kotlin IDE does understand org.jetbrains.annotations.PropertyKey 11, but it does not always work. I have had problems if the bundle contains more than one language.
Example:
fun message(#PropertyKey(resourceBundle = "Messages") id: String) =
ResourceBundle.getBundle("Messages").getString(sid) ?: "###$id###"
For more visit:https://developer.android.com/studio/write/lint#src

Related

Kotlin // Solve the example in a line

How to solve an example in a string?
Let's say we have val example : String = "3+5"
So how do I solve this example? Or if val example : String = "3*5/3"
Two ways to achieve it:
Keval - 3rd party dependency
You can either use Keval.eval("(3+4)(2/8 * 5) % PI") or as an extension function on String, "(3+4)(2/8 * 5) % PI".keval(). This will return the calculated value as Double. For your example, "3*5/3".keval().
To use it, add implementation("com.notkamui.libs:keval:0.8.0") in dependencies in app level build.gradle file and sync gradle. Then, use it in any file as mentioned in the above para, put the cursor on the line and press Alt + Enter (or hover for suggestions) to import the necessary imports.
Look into its Readme.md on the provided link for more usage and implementation details.
Custom String parsing using BODMAS rule
You can split the string using the BODMAS rule, parse the split array as int/double, if it throws exception, it means the substring is an expression too, again split it using BODMAS, parse and perform the calculation.

Is there a Kotlin "eval"

I have a bunch of strings like these in my already existing and quit big template file:
Hello $World I say hello to $User, too
I was thinking I could somehow let kotlin parse/search&replace this file as a kotlin string, and I'd just have to set the variables World and User to get an evaluated string... How is this possible?
This is not a kotlin source file, but a file that's beeing read by my kotlin program.
Why I want to do this? I used bash's envsubst before, and had to move away from this, since things were getting too complicated. But now I have no easy way to replace strings in a file anymore...
Thanks
What you want is called a template engine.
You don't really need an eval (which would allow running a full Kotlin application from a String) in this case.
For example, FreeMarker templates use a syntax that's similar to Kotlin template Strings, so a template may look like this:
<h1>Welcome ${user}!</h1>
Then, from Kotlin, you can evaluate the template with a Map holding the template bindings (variables the template can use) like this:
val user = "joe"
val bindings = mapOf("user" to user)
val cfg = new Configuration(Configuration.VERSION_2_3_29)
cfg.directoryForTemplateLoading = File("/where/you/store/templates")
val template = cfg.getTemplate("test.ftlh")
// write the resolved template to stdout
val out = OutputStreamWriter(System.out)
template.process(bindings, out)
See a Java example here: https://freemarker.apache.org/docs/pgui_quickstart_all.html
There are many other template engines, and the KTor site lists a few:
https://ktor.io/docs/working-with-views.html
If you're using KTor, BTW, it makes it much easier to use template engines... your framework may even have similar.
Warning: Please see my other answer first: you probably don't want to run a full Kotlin script just to parse some text file with variables... use a template engine for that.
It's possible to execute Kotlin scripts, i.e. eval Kotlin code, but it requires that you basically ship the Kotlin compiler with your application.
This GitHub project, KtsRunner, for example, does that, so you can do this:
val scriptContent = "5 + 10"
val fromScript: Int = KtsObjectLoader().load<Int>(scriptContent))
println(fromScript)
// >> 15
It requires some hacking though, is very slow and it uses a bunch of Kotlin "internal" APIs to work.
See the full list of libraries this project uses here:
https://github.com/s1monw1/KtsRunner/blob/master/lib/build.gradle.kts#L21
A "proper" KEEP proposal (discussion here) exists to add first-class support for this in Kotlin, but it's not finalized yet.
Currently, it looks something like this:
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MainKtsScript>()
val evaluationConfiguration = createJvmEvaluationConfigurationFromTemplate<MainKtsScript>()
return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConfiguration, evaluationConfiguration)
}
But it'll probably change before being released.

Kotlin Native how to convert ByteArray to String?

I was playing with the kotlin-native samples.
I wonder how I could get String from pinned ByteArray. Just want to print it in the console.
If you need a solution for the JVM, since stringFromUtf8 is only available for the native platform, use toString with a Charset as argument:
val byteArray = "Hello World".toByteArray(Charsets.UTF_8)
val str = byteArray.toString(Charsets.UTF_8)
If you specifically only want to target native, use Sin's solution.
It seems that this API has changed
Now just use this: string.toUtf8(start, end)
https://github.com/JetBrains/kotlin-native/commit/cba7319e982ed9ba2dceb517a481cb54ed1b9352#diff-45a5f8d37067266e27b76d1b68f01173
Legacy version:
Use stringFromUtf8
/**
* Converts an UTF-8 array into a [String]. Replaces invalid input sequences with a default character.
*/
fun ByteArray.stringFromUtf8(start: Int = 0, size: Int = this.size) : String =
stringFromUtf8Impl(start, size)
See here.
And if the byteArray is like CPointer<ByteVar> by interoperating C APIs, pleace use .toKString() in Kotlin-Native
The OKIO library has a helper method for this commonToUtf8String
One can simply copy the method code don't need to add the entire lib just for this.
Another solution that could be used everyone but especially makes sense looking for a Kotlin Multiplatform solution and using ktor library already is using io.ktor.utils.io.core.String function directly without adding extra third pary library or extra actual class implementation. For example:
Your build.gradle.kts for all platforms:
implementation("io.ktor:ktor-client-core:${Versions.ktor}")
implementation("io.ktor:ktor-client-android:${Versions.ktor}")
implementation("io.ktor:ktor-client-apache:${Versions.ktor}")
implementation("io.ktor:ktor-client-ios:${Versions.ktor}")
Then use it
io.ktor.utils.io.core.String(byteArray, offset, length, Charsets.UTF_8)

How to pass a string to a var without escape symbol in Kotlin?

I hope to pass the string {"name":"My Settings 1"} to a var aa
I have to write it using the code var aa=" {\"name\":\"My Settings 1\"} "
Is there a simple way in Kotlin when I use Android Studio 3.0 ?
I know <![CDATA[...]]> is good for XML content
The simplest thing you can do in Kotlin is use raw strings with triple quote marks:
val a = """{"name":"My Settings 1"}"""
For a tooling solution instead of a language solution (so this works both in Kotlin and Java), you can use language injection in Android Studio or IntelliJ.
Create a string, and invoke intention actions on it with Alt + Enter. Select Inject language or reference, and then JSON.
Use Alt + Enter again, and choose Edit JSON Fragment.
Edit the raw JSON in the panel that appears on the bottom, and IntelliJ will automatically mirror its contents into the string, escaping any characters that have to be escaped.
Escaping special chars in regular Strings, like in your example, is what has to be done with Java and also Kotlin:
"{\"name\":\"My Settings 1\"}"
Kotlin offers raw Strings to evade this. In these raw Strings there's no need to escape special chars, which shows the following:
"""{"name":"My Settings 1"}"""
Raw Strings are delimited by a triple quote (""").
Read the docs here.

Convert Java Collection.toArray to kotlin

Please help me convert this java code to kotlin, I try many times but I can't
ObjectStream<DocumentSample> bin
= ObjectStreamUtils.createObjectStream(categoryStreams.toArray(new ObjectStream[0]));
In Kotlin, you may use toTypedArray() to get an Array from a List:
categoryStreams.toTypedArray() //Array<ObjectStream<DocumentSample>>
Then, you can use spread operator to prefix the array and pass it to ObjectStreamUtils.createObjectStream():
val bin = ObjectStreamUtils.createObjectStream<DocumentSample>(*categoryStreams.toTypedArray())
Assuming the categoryStreams object is one of the Collection type(List, Set, etc.), you can call kotlin's extension method toTypedArray on it to get an array of the ObjectStream:
This should work:
val bin = ObjectStreamUtils.createObjectStream(categoryStreams.toTypedArray())
If the method accepts vararg of ObjectStream, then you can use spread operator * to spread array to vararg:
val bin = ObjectStreamUtils.createObjectStream(*categoryStreams.toTypedArray())
To convert Java file to Kotlin
On the main menu, point to Code menu.
Choose Convert Java File to Kotlin File.
Done.
In your case it converts to:
val bin = ObjectStreamUtils.createObjectStream(categoryStreams.toArray(arrayOfNulls<ObjectStream>(0)))
var bin = ObjectStreamUtils.createObjectStream(categoryStreams.toArray(arrayOfNulls(0)))
the above code is converted your code to kotlin.
It sounds like a type inference problem. Try the code below. I add the declaration for categoryStreams. Not sure how it is declared in your code. But this is a reasonable declaration from looking at the code on github.
val categoryStreams = arrayListOf<ObjectStream<DocumentSample>>()
val bin = ObjectStreamUtils.createObjectStream(categoryStreams.toArray(arrayOfNulls<ObjectStream<DocumentSample>>(0)))
The idea is to provide the correct type for inference (which the converter neglected to provide). The original java did not infer the type, it was an explicit cast.