build.gradle: How to convert Groovy-ish custom task to Kotlin-ish? - kotlin

I have such custom task written via Groovy:
task systemTest(type: Test, description: 'Runs the system tests', group: 'Verification'){
exclude "**/**Smoke.class"
exclude "**/**Test.class"
exclude "**/**IT.class"
include "**/**ST.class"
useJUnitPlatform()
testLogging {
exceptionFormat = 'full'
events "passed", "skipped", "failed", "standardOut", "standardError"
showStandardStreams = true
showCauses true
showExceptions true
showStackTraces true
}
afterSuite { desc, result ->
if (!desc.parent) {
def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
def startItem = '| ', endItem = ' |'
def repeatLength = startItem.length() + output.length() + endItem.length()
println('\n\n\n' + ('-' * repeatLength) + "\n$startItem $output $endItem\n" + ('-' * repeatLength) + '\n\n\n')
}
}
systemTest.finalizedBy('allureReport')
}
Tried to convert this snippet via tools, e.g. this one or this one
and then refactor script manually:
val systemTest by tasks.registering(Test::class) {
description = "Runs the system tests"
group = "Verification"
exclude("**/**Smoke.class")
exclude("**/**Test.class")
exclude("**/**IT.class")
include("**/**ST.class")
useJUnitPlatform()
testLogging {
exceptionFormat = "full"
events = setOf("passed", "skipped", "failed", "standardOut", "standardError")
showStandardStreams = true
showCauses = true
showExceptions = true
showStackTraces = true
}
afterSuite { desc, result ->
if (!desc.parent) {
val output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
val startItem = "| "
val endItem = " |"
val repeatLength = startItem.length() + output.length() + endItem.length()
println("\n\n\n" + ("-" * repeatLength) + "\n$startItem $output $endItem\n" + ("-" * repeatLength) + "\n\n\n")
}
}
systemTest.finalizedBy("allureReport")
}
but nevertheless got a lot of errors on ./gradlew systemTest:
* What went wrong:
Script compilation errors:
Line 44: exceptionFormat = "full"
^ Type mismatch: inferred type is String but TestExceptionFormat! was expected
Line 45: events = setOf("passed", "skipped", "failed", "standardOut", "standardError")
^ Type mismatch: inferred type is String but TestLogEvent! was expected
Line 45: events = setOf("passed", "skipped", "failed", "standardOut", "standardError")
^ Type mismatch: inferred type is Set<String> but (Mutable)Set<TestLogEvent!>! was expected
Line 51: afterSuite { desc, result ->
^ Type mismatch: inferred type is ([ERROR : <Unknown lambda parameter type>], [ERROR : <Unknown lambda parameter type>]) -> Unit but Closure<(raw) Any!>! was expected
Line 51: afterSuite { desc, result ->
^ Cannot infer a type for this parameter. Please specify it explicitly.
Line 51: afterSuite { desc, result ->
^ Cannot infer a type for this parameter. Please specify it explicitly.
Line 56: val repeatLength = startItem.length() + output.length() + endItem.length()
^ Expression 'length' of type 'Int' cannot be invoked as a function. The function 'invoke()' is not found
Line 56: val repeatLength = startItem.length() + output.length() + endItem.length()
^ Expression 'length' of type 'Int' cannot be invoked as a function. The function 'invoke()' is not found
Line 56: val repeatLength = startItem.length() + output.length() + endItem.length()
^ Expression 'length' of type 'Int' cannot be invoked as a function. The function 'invoke()' is not found
Line 57: println("\n\n\n" + ("-" * repeatLength) + "\n$startItem $output $endItem\n" + ("-" * repeatLength) + "\n\n\n")
^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public inline operator fun BigDecimal.times(other: BigDecimal): BigDecimal defined in kotlin
public inline operator fun BigInteger.times(other: BigInteger): BigInteger defined in kotlin
Line 57: println("\n\n\n" + ("-" * repeatLength) + "\n$startItem $output $endItem\n" + ("-" * repeatLength) + "\n\n\n")
^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public inline operator fun BigDecimal.times(other: BigDecimal): BigDecimal defined in kotlin
public inline operator fun BigInteger.times(other: BigInteger): BigInteger defined in kotlin
Line 60: systemTest.finalizedBy("allureReport")
^ Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly
12 errors
java -version:
java -version
openjdk version "11.0.13" 2021-10-19 LTS
OpenJDK Runtime Environment Corretto-11.0.13.8.1 (build 11.0.13+8-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.13.8.1 (build 11.0.13+8-LTS, mixed mode)
used plugins in build script:
plugins {
id("org.jetbrains.kotlin.jvm") version "1.7.10"
id("java")
id("io.qameta.allure") version "2.11.2"
}
Any help in pointing out what am I doing wrong would be highly appreciated.

Related

IntelliJ IDEA Live Template Groovy script error

I've created a Groovy script based Live Template for DataGrip, but it always throws a startup error but it works on online groove executor:
def result = '';
def i=1;
_1.split().eachWithIndex { item, index ->
def ans = '';
if (_2=='id' && index==0) {
return;
} else if (_2=='uuid' && index==0) {
ans = 'gen_random_uuid()';
} else {
ans = '$'+i;
i++;
}
if (index.next() != _1.split().size()) {
ans= ans + ','
}
result = result + ans
};
return result;
Here is the error:
startup failed:
Script1.groovy: 1: expecting '}', found 'if' # line 1, column 267.
'$' + i;
i++;
} if (index.
^
1 error
Solution is to put a semicolon after each if closes.

I'm getting a compile time error that I don't know how to solve: error: expecting property name or receiver type - Kotlin

/**
* Example:
* var li = ListNode(5)
* var v = li.`val`
* Definition for singly-linked list.
* class ListNode(var `val`: Int) {
* var next: ListNode? = null
* }
*/
class Solution {
fun mergeTwoLists(l1: ListNode?, l2: ListNode?): ListNode? {
var head : ListNode?
var tail: ListNode?
var firstPointer : ListNode? = l1
var secondPointer : ListNode? = l2
while( firstPointer != null || secondPointer != null){
var next : ListNode?
if (firstPointer == null || secondPointer == null){
if (secondPointer != null){
next.val = secondPointer.val
secondPointer = secondPointer.next
}else {
next.val = firstPointer.val
firstPointer = firstPointer.next
}
}else if(firstPointer.val <= secondPointer.val) {
next.val = firstPointer.val
firstPointer = firstPointer.next
}else if(secondPointer.val <= firstPointer.val ){
next.val = secondPointer.val
secondPointer = secondPointer.next
}
if (head == null){
head = next
tail = next
}else {
tail.next = next
tail = next
}
}
return head
}
}
getting a lot of compile time errors
Line 22: Char 29: error: expecting property name or receiver type
next.val = secondPointer.val
^
Line 25: Char 29: error: expecting property name or receiver type
next.val = firstPointer.val
^
Line 28: Char 39: error: type expected
}else if(firstPointer.val <= secondPointer.val) {
^
val is a keyword in kotlin. If you want to use it as a name of a field, you need to wrap it into backticks: secondPointer.`val`, firstPointer.`val` (actualy, code example in the comment before your code shows that).
Well, I don't know Kotlin well, but from my perspective this might be the problem:
var next : ListNode?
Because you define a variable, but it is still null.
When you then try to access its field val you can't, because null has no such field.

Android Studios: Type inference failed. The value of the type parameter T should be mentioned in input types

Having an error with Android Studios (Kotlin)
Error:
e: Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
fun devId(): Any {
var str = Build.CPU_ABI
if (Build.VERSION.SDK_INT >= 21) {
var i = 0
val hashSet = HashSet(listOf(arrayOf("armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64", "mips", "mips64")))
val strArr = Build.SUPPORTED_ABIS
val length = strArr.size
while (true) {
if (i >= length) { break }
val str2 = strArr[i]
if (hashSet.contains(str2)) {
str = str2
break
}
i++
}
}
return println(Build.BOARD + Build.BRAND + str + Build.DEVICE + Build.MANUFACTURER + Build.MODEL + Build.PRODUCT)
}
The problem is in hashSet.contains(str2). This expression is always false. Because hashSet type is HashSet<Array<String>> but str2 is String You could pass to function contains only Array<String>
Looks like you could rewrite yours code as:
fun devId() {
val str = if (Build.VERSION.SDK_INT >= 21) {
Build.SUPPORTED_ABIS
.firstOrNull { it in setOf("armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64", "mips", "mips64") }
?: Build.CPU_ABI
} else Build.CPU_ABI
return println(Build.BOARD + Build.BRAND + str + Build.DEVICE + Build.MANUFACTURER + Build.MODEL + Build.PRODUCT)
}

error: expecting property name or receiver type - Kotlin

Not able to figure out what is wrong with below code and why I am getting below error :
/**
* Example:
* var ti = TreeNode(5)
* var v = ti.`val`
* Definition for a binary tree node.
* class TreeNode(var `val`: Int) {
* var left: TreeNode? = null
* var right: TreeNode? = null
* }
*/
class Solution {
fun pathSum(root: TreeNode?, sum: Int): List<List<Int>> {
var result : List<MutableList<Int>> = listOf(mutableListOf())
var path : MutableList<Int> = mutableListOf()
dfs(root, sum, result, path)
return result
}
fun dfs(root: TreeNode?, sum: Int, result: List<MutableList<Int>>, path: MutableList<Int>){
if(root == null) return
path.add(sum)
dfs(root.left, sum - root.val, result, path)
dfs(root.right, sum - root.val, result, path)
if(sum == 0 &&
root.left == null &&
root.right == null) {
result.add(path)
}
path.remove(path.size() - 1)
}
}
I am getting below lots of compile time errors while running above code, new to Kotlin struggling to figure out root cause :
Line 24: Char 38: error: expecting property name or receiver type
dfs(root.left, sum - root.val, result, path)
^
Line 24: Char 46: error: expecting an element
dfs(root.left, sum - root.val, result, path)
val is a keyword in kotlin. If you want to use it as a name of a field,
you need to wrap it into backticks: `val`
(actually, the code example in the comment before your code shows that).

Antlr setText not working in the way I expected

I have a requirement to convert an identifier into a beanutil string for retrieving an item from an object. The the identifiers to string conversions look like:
name ==> name
attribute.name ==> attributes(name)[0].value
attribute.name[2] ==> attributes(name)[2].value
address.attribute.postalcode ==> contactDetails.addresses[0].attributes(postalcode)[0].value
address[2].attribute.postalcode ==> contactDetails.addresses[2].attributes(postalcode)[0].value
address[2].attribute.postalcode[3] ==> contactDetails.addresses[2].attributes(postalcode)[3].value
Now I have decided to do this using antlr as I feel its probably going to be just as quick as using a set of 'if' statements. Feel free to tell me I'm wrong.
Right now, I've got this partial working using antlr, however once I start doing the 'address' ones, the setText part seems to stop working for Attribute.
Am I doing this the correct way or is there a better way of using antlr to get the result I want?
grammar AttributeParser;
parse returns [ String result ]
: Address EOF { $result = $Address.text; }
| Attribute EOF { $result = $Attribute.text; }
| Varname EOF { $result = $Varname.text; }
;
Address
: 'address' (Arraypos)* '.' Attribute { setText("contactDetails.addresses" + ($Arraypos == null ? "[0]" : $Arraypos.text ) + "." + $Attribute.text); }
;
Attribute
: 'attribute.' Varname (Arraypos)* { setText("attributes(" + $Varname.text + ")" + ($Arraypos == null ? "[0]" : $Arraypos.text ) + ".value"); }
;
Arraypos
: '[' Number+ ']'
;
Varname
: ('a'..'z'|'A'..'Z')+
;
Number
: '0'..'9'+
;
Spaces
: (' ' | '\t' | '\r' | '\n')+ { setText(" "); }
;
Below are two unit tests, the first returns what I expect, the second doesn't.
#Test
public void testSimpleAttributeWithArrayRef() throws Exception {
String source = "attribute.name[2]";
ANTLRStringStream in = new ANTLRStringStream(source);
AttributeParserLexer lexer = new AttributeParserLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
AttributeParserParser parser = new AttributeParserParser(tokens);
String result = parser.parse();
assertEquals("attributes(name)[2].value", result);
}
#Test
public void testAddress() throws Exception {
String source = "address.attribute.postalcode";
ANTLRStringStream in = new ANTLRStringStream(source);
AttributeParserLexer lexer = new AttributeParserLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
AttributeParserParser parser = new AttributeParserParser(tokens);
String result = parser.parse();
System.out.println("Result: " + result);
assertEquals("contactDetails.addresses[0].attributes(postalcode)[0].value", result);
}
No, you can't do (Arraypos)* and then refer to the contents as this: $Arraypos.text.
I wouldn't go changing the inner text of the tokens, but create a couple of parser rules and let them return the appropriate text.
A little demo:
grammar AttributeParser;
parse returns [String s]
: input EOF {$s = $input.s;}
;
input returns [String s]
: address {$s = $address.s;}
| attribute {$s = $attribute.s;}
| Varname {$s = $Varname.text;}
;
address returns [String s]
: Address arrayPos '.' attribute
{$s = "contactDetails.addresses" + $arrayPos.s + "." + $attribute.s;}
;
attribute returns [String s]
: Attribute '.' Varname arrayPos
{$s = "attributes(" + $Varname.text + ")" + $arrayPos.s + ".value" ;}
;
arrayPos returns [String s]
: Arraypos {$s = $Arraypos.text;}
| /* nothing */ {$s = "[0]";}
;
Attribute : 'attribute';
Address : 'address';
Arraypos : '[' '0'..'9'+ ']';
Varname : ('a'..'z' | 'A'..'Z')+;
which can be tested with:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String[][] tests = {
{"name", "name"},
{"attribute.name", "attributes(name)[0].value"},
{"attribute.name[2]", "attributes(name)[2].value"},
{"address.attribute.postalcode", "contactDetails.addresses[0].attributes(postalcode)[0].value"},
{"address[2].attribute.postalcode", "contactDetails.addresses[2].attributes(postalcode)[0].value"},
{"address[2].attribute.postalcode[3]", "contactDetails.addresses[2].attributes(postalcode)[3].value"}
};
for(String[] test : tests) {
String input = test[0];
String expected = test[1];
AttributeParserLexer lexer = new AttributeParserLexer(new ANTLRStringStream(input));
AttributeParserParser parser = new AttributeParserParser(new CommonTokenStream(lexer));
String output = parser.parse();
if(!output.equals(expected)) {
throw new RuntimeException(output + " != " + expected);
}
System.out.printf("in = %s\nout = %s\n\n", input, output, expected);
}
}
}
And to run the demo do:
java -cp antlr-3.3.jar org.antlr.Tool AttributeParser.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main
which will print the following to the console:
in = name
out = name
in = attribute.name
out = attributes(name)[0].value
in = attribute.name[2]
out = attributes(name)[2].value
in = address.attribute.postalcode
out = contactDetails.addresses[0].attributes(postalcode)[0].value
in = address[2].attribute.postalcode
out = contactDetails.addresses[2].attributes(postalcode)[0].value
in = address[2].attribute.postalcode[3]
out = contactDetails.addresses[2].attributes(postalcode)[3].value
EDIT
Note that you can also let parser rules return more than just one object like this:
bar
: foo {System.out.println($foo.text + ", " + $foo.number);}
;
foo returns [String text, int number]
: 'FOO' {$text = "a"; $number = 1;}
| 'foo' {$text = "b"; $number = 2;}
;