Is there any way to catch unhandled exceptions in compile time in Intellij IDE (or some other way ?)
fun main() {
val list = listOf(1,2)
println(list.first())
}
As you can see list.first() throws an exception (if the list is empty), but I don't get any warning in the IDE to handle it properly. I already tried Csense plugin but unfortunately no luck. I'm not sure how much work it takes to achieve this stuff, I have looked at Intellij PSI element to know if is there any way to recursively trace the function call and to catch some unhandled exceptions, but it's not straight forward as I thought :)
It would be great if someone share the details if they already achieved this in their kotlin project.
Note:
The reason I asked this question is that I'm working on a project which uses kotlin arrow lib to make the code more functional style. So they use Either to handle errors explicitly instead of try/catch.
Related
It is not really a Kotlin question, maybe an Intellij question, I don't know.
Assume we have a data class
data class Person(val name: String = "untitled", val age: Int = 20)
And we have a function
fun factory(cstr: ()->Person) : Person {
return cstr()
}
Then we can invoke factory(::Person) and obtain an instance of Person class with default constructor parameters.
The fun factory can be invoked successfully wherever. But in IntelliJ I get a red underline error
Look like the IDE failed to recognize that there is a default constructor.
However, If I change the code like that, the error goes away. Everything runs perfectly and no error is shown in the IDE.
I am using IntelliJ 2020.2 and Kotlin 1.4.10.
Maybe it is about some IntelliJ inspection rules, but I cannot find one related.
Further, it is a piece of old code that showed no error before (maybe 5 months ago). I am not sure what has bee change since then caused the error.
So the problem is why is Intellij show error for lambda version and not for KFunction version?
I assume invoking factory like this works fine:
factory(() -> Person())
Then it seems your version of the Kotlin IDE plugin does not handle constructor references well in this case. The compiler does, since the code works. If the IDE plugin version is the latest, please file a bug at https://youtrack.jetbrains.com/issues/KT
I reproduced the problem with old inference enabled in the build.gradle file: freeCompilerArgs += ["-XXLanguage:-NewInference"]. Please make sure you're using new (default) type inference in Kotlin 1.4+. So, remove the compiler argument, that should fix the IDE highlighting after Gradle project reimport into IDEA.
I have a jenkins.gdsl file defining some bindings I'm using in my Groovy script. In addition, I'd like to use the #TypeChecked annotation on my methods to get some guarantees about built code.
My jenkins.gdsl file looks like:
contributor(context(scope: scriptScope())) {
// some definitions
}
And then my script.groovy looks like:
#TypeChecked(extensions='jenkins.gdsl')
void doStuff() {
// ...
}
IntelliJ IDEA autocomplete works, but when building my project I get an error in my jenkins.gdsl file:
Error:Groovyc: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.scriptScope() is applicable for argument types: () values: []
Removing (extensions='jenkins.gdsl') gets rid of this error, but then I lose my GDSL definitions when building, so that's a no-go.
It feels like the solution would involve bringing in IntelliJ's standardDsls. I am not at all sure how to do this, or whether it is in fact the correct approach.
#TypeChecked is a Groovy compiler annotation that can run some code during compilation.
But gdsl is an IntelliJ IDEA-specific script that's used only by the IDE to provide some completion and other coding assistance. It doesn't have anything in common with the compiler, and neither of those know anything of each other. So you can remove the extensions value, as it won't provide any typechecking during compilation.
The Kotlin standard library has a neat function require which is something like a runtime assert:
#kotlin.internal.InlineOnly
public inline fun require(value: Boolean, lazyMessage: () -> Any): Unit {
contract {
returns() implies value
}
if (!value) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
}
}
When I am debugging, I would like to be able to set a breakpoint in this function, just before the exception is thrown. Like this, I would have the entire stacktrace and local variables visible in the debugger once a requirement is broken. However, this doesn't seem to work:
At first I thought that this is because require is an inline function. I made an experiment with one of my inline functions and the debugger halts as expected.
As a workaround I tried to set the debugger to break on exceptions, but the framework I am working with (Spring) throws a barrage of exceptions on each application start, making it extremely tedious to ignore the irrelevant exceptions.
I would like to know how to make it work, but I am also interested about the why of "it doesn't work".
It's currently not possible to set breakpoints in Kotlin for functions marked with a InlineOnly annotation, and require is one of such functions. Inline functions marked with this annotation don't provide additional debug information in order to save a line from the call site untouched in stack-traces, but it also ruins setting breakpoints inside (https://youtrack.jetbrains.com/issue/KT-24306).
You have spotted one workaround - using exception breakpoints (https://www.jetbrains.com/help/idea/creating-exception-breakpoints.html). IllegalArgumentException would be the best class in this case.
If there're calls in your code that don't work, they might be replaced to custom function as another workaround.
(The answer was updated. The previous version erroneously claimed that breakpoints in require might work for some calls.)
I have a maybe silly question. I coming from programming languages with exception handling, e.g. C++ and C#. At the time of Swift 1 I was confronted with the Cocoa Style with error objects (which somewhat reminded me at the ErrorObject in Microsoft COM).
After a time I began to use for my side project app an error handling pattern, in which I used a function parameter (closure) for error handling:
public typealias FailureBlock = (error:NSError!)->Void
JournalEntryStorage.instance.createJournalEntry(journalInfo, failure:
{
error in
NSLog("Watch App saveNewEntryInJournal: \(error.description)")
})
This solution seems nice at the time, because the function parameter forces me to code the error handling logic or I could simply make a call to a passed error handler function.
Now we have a solid error handling in place with Swift 2. Should I change my code completely to the new pattern? There is a lot of code.
How do you deal with your (legacy) code and the new error pattern?
By the way: I found the original Cocoa way with passing an error pointer and dealing with it so ugly in Swift 1. Maybe my method is more ugly but for me it seemed working.
I have decided for following solution and close the question:
a) I leave my old error handling pattern for all asynchronous function calls.
b) I am converting all synchronous functions to the new error handling scheme.
First impression. The code is much more readable.
If an exception occurs in a try block, how is execution transferred to the catch block? This is not a C#/Java/C++ question, I'm just wondering how it works internally.
this is not a c#/java/c++ question. How it works internally,how the line knows to go catch statement.
How this works internally makes this pretty much a c#/java/C++ question (because it will be implemented differently).
In Java, a try block installs itself into a special table (in the class file). When the JVM throws an exception, it looks at that table to see where the next catch or finally block to go to is.
When an exception occurs a special instruction is executed (usually called interrupt). This leads to executing a generic error handler that deduces which is the latest installed suitable exception handler. That handler is then executed.
There is a difference how exceptions are technically handled between natively compiled languages such as C++ and languages using byte-code being executed on a virtual machine such as Java or C#.
C++ compilers usually generate code that protocols the information needed for exception handling at runtime. A dedicated data structure is used to remember entrance/exit of try blocks and the associated exception handler. When an exception occurs, an interrupt is generated and control is passed to the OS which in turn inspects the call stack and determines which exception handler to call.
Further details are pretty well explained in the following article by Vishal Kochhar:
How a C++ compiler implements exception handling
In Java or .NET there is no need for the overhead of maintaining exception handling information as the runtime will be able to introspect the byte code to find the relevant exception handler. As a consequence, only exceptions that are actually thrown are causing an overhead.
It is basically parsing fundamentals of the language.
You can get all info at Here
it should work in all langues somewhat like this:
if (error_occured xy while doing things in try){
call_catch_part(error xy)
}
you could do the same in C even though there is no exception handling per se.
There you would use setjmp/longjmp unfortunately you then do not get the stack unwinding and have to handle all the nitty-gritty yourself.