Cleanup and additional tests

This commit is contained in:
Brian Norman
2021-04-24 12:31:26 -05:00
parent 4a9e145d55
commit b4ce1c12b6
13 changed files with 517 additions and 180 deletions
@@ -16,6 +16,9 @@
package com.bnorm.power
import com.bnorm.power.delegate.FunctionDelegate
import com.bnorm.power.delegate.LambdaFunctionDelegate
import com.bnorm.power.delegate.SimpleFunctionDelegate
import com.bnorm.power.diagram.IrTemporaryVariable
import com.bnorm.power.diagram.Node
import com.bnorm.power.diagram.buildDiagramNesting
@@ -32,28 +35,18 @@ import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.utils.asString
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irCallOp
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.builders.irString
import org.jetbrains.kotlin.ir.builders.parent
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.path
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
@@ -68,7 +61,6 @@ import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isFunctionOrKFunction
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
class PowerAssertCallTransformer(
@@ -81,17 +73,27 @@ class PowerAssertCallTransformer(
override fun visitCall(expression: IrCall): IrExpression {
val function = expression.symbol.owner
val fqName = function.kotlinFqName
if (function.valueParameters.isEmpty() || functions.none { fqName == it })
if (function.valueParameters.isEmpty() || functions.none { fqName == it }) {
return super.visitCall(expression)
}
// Find a valid delegate function or do not translate
// TODO better way to determine which delegate to actually use
val delegates = findDelegates(function)
val delegate = delegates.maxByOrNull { it.function.valueParameters.size } ?: run {
val valueType = function.valueParameters[0].type.asString()
val delegate = delegates.maxByOrNull { it.function.valueParameters.size }
if (delegate == null) {
val valueTypesTruncated = function.valueParameters.subList(0, function.valueParameters.size - 1)
.joinToString(", ") { it.type.asString() }
val valueTypesAll = function.valueParameters.joinToString(", ") { it.type.asString() }
messageCollector.warn(
expression,
"Unable to find overload for function $fqName callable as $fqName($valueType, String) or $fqName($valueType, () -> String) for power-assert transformation"
expression = expression,
message = """
|Unable to find overload of function $fqName for power-assert transformation:
| - $fqName($valueTypesTruncated, String)
| - $fqName($valueTypesTruncated, () -> String)
| - $fqName($valueTypesAll, String)
| - $fqName($valueTypesAll, () -> String)
""".trimMargin()
)
return super.visitCall(expression)
}
@@ -110,7 +112,7 @@ class PowerAssertCallTransformer(
.map { arg -> arg?.let { buildTree(it) } }
}
// If all roots are null, all parameters are constants and expression need not be transformed
// If all roots are null, there are no transformable parameters
if (roots.all { it == null }) {
messageCollector.info(expression, "Expression is constant and will not be power-assert transformed")
return super.visitCall(expression)
@@ -118,7 +120,7 @@ class PowerAssertCallTransformer(
val symbol = currentScope!!.scope.scopeOwnerSymbol
val builder = DeclarationIrBuilder(context, symbol, expression.startOffset, expression.endOffset)
return builder.diagram(expression, delegate, symbol, messageArgument, roots)
return builder.diagram(expression, delegate, messageArgument, roots)
// .also { println(expression.dump()) }
// .also { println(it.dump()) }
// .also { println(expression.dumpKotlinLike()) }
@@ -128,7 +130,6 @@ class PowerAssertCallTransformer(
private fun DeclarationIrBuilder.diagram(
original: IrCall,
delegate: FunctionDelegate,
scopeSymbol: IrSymbol,
messageArgument: IrExpression?,
roots: List<Node?>,
index: Int = 0,
@@ -136,63 +137,43 @@ class PowerAssertCallTransformer(
variables: List<IrTemporaryVariable> = listOf()
): IrExpression {
if (index >= roots.size) {
val lambda = messageArgument?.asSimpleLambda()
val title = when {
messageArgument is IrConst<*> -> messageArgument
messageArgument is IrStringConcatenation -> messageArgument
lambda != null -> lambda.deepCopyWithSymbols(parent).inline(parent)
.transform(ReturnableBlockTransformer(context, scopeSymbol), null)
messageArgument != null -> {
val invoke = messageArgument.type.classOrNull!!.owner.functions
.single { it.name == OperatorNameConventions.INVOKE }
irCallOp(invoke.symbol, invoke.returnType, messageArgument)
}
// TODO what should the default message be?
roots.size == 1 && original.getValueArgument(0)!!.type.isBoolean() -> irString("Assertion failed")
else -> null
}
val prefix = title?.deepCopyWithSymbols(parent)
val prefix = buildMessagePrefix(messageArgument, roots, original)?.deepCopyWithSymbols(parent)
val diagram = irDiagramString(file, fileSource, prefix, original, variables)
return delegate.buildCall(this, original, arguments, diagram)
} else {
val root = roots[index]
if (root == null) {
return diagram(
original,
delegate,
scopeSymbol,
messageArgument,
roots,
index + 1,
arguments + original.getValueArgument(index),
variables
)
val newArguments = arguments + original.getValueArgument(index)
return diagram(original, delegate, messageArgument, roots, index + 1, newArguments, variables)
} else {
return buildDiagramNesting(root) { argument, newVariables ->
diagram(
original,
delegate,
scopeSymbol,
messageArgument,
roots,
index + 1,
arguments + argument,
variables + newVariables
)
val newArguments = arguments + argument
diagram(original, delegate, messageArgument, roots, index + 1, newArguments, variables + newVariables)
}
}
}
}
private interface FunctionDelegate {
val function: IrFunction
fun buildCall(
builder: IrBuilderWithScope,
original: IrCall,
arguments: List<IrExpression?>,
message: IrExpression
): IrExpression
private fun DeclarationIrBuilder.buildMessagePrefix(
messageArgument: IrExpression?,
roots: List<Node?>,
original: IrCall
): IrExpression? {
val lambda = messageArgument?.asSimpleLambda()
return when {
messageArgument is IrConst<*> -> messageArgument
messageArgument is IrStringConcatenation -> messageArgument
lambda != null -> lambda.deepCopyWithSymbols(parent).inline(parent)
.transform(ReturnableBlockTransformer(context, scope.scopeOwnerSymbol), null)
messageArgument != null -> {
val invoke = messageArgument.type.classOrNull!!.owner.functions
.single { it.name == OperatorNameConventions.INVOKE }
irCallOp(invoke.symbol, invoke.returnType, messageArgument)
}
// TODO what should the default message be?
roots.size == 1 && original.getValueArgument(0)!!.type.isBoolean() -> irString("Assertion failed")
else -> null
}
}
private fun findDelegates(function: IrFunction): List<FunctionDelegate> {
@@ -203,81 +184,15 @@ class PowerAssertCallTransformer(
.mapNotNull { overload ->
val parameters = overload.owner.valueParameters
if (parameters.size !in values.size..values.size + 1) return@mapNotNull null
if (!parameters.zip(values)
.all { (param, value) -> value.type.isAssignableTo(param.type) }
) return@mapNotNull null
if (!parameters.zip(values).all { (param, value) -> value.type.isAssignableTo(param.type) }) {
return@mapNotNull null
}
val messageParameter = parameters.last()
return@mapNotNull when {
isStringSupertype(messageParameter.type) -> {
object : FunctionDelegate {
override val function = overload.owner
override fun buildCall(
builder: IrBuilderWithScope,
original: IrCall,
arguments: List<IrExpression?>,
message: IrExpression
): IrExpression = with(builder) {
irCall(overload, type = original.type).apply {
dispatchReceiver = original.dispatchReceiver?.deepCopyWithSymbols(parent)
extensionReceiver = original.extensionReceiver?.deepCopyWithSymbols(parent)
for (i in 0 until original.typeArgumentsCount) {
putTypeArgument(i, original.getTypeArgument(i))
}
for ((i, argument) in arguments.withIndex()) {
putValueArgument(i, argument?.deepCopyWithSymbols(builder.scope.getLocalDeclarationParent()))
}
putValueArgument(parameters.size - 1, message)
}
}
}
}
isStringFunction(messageParameter.type) -> {
object : FunctionDelegate {
override val function = overload.owner
override fun buildCall(
builder: IrBuilderWithScope,
original: IrCall,
arguments: List<IrExpression?>,
message: IrExpression
): IrExpression = with(builder) {
val scope = this
val lambda = builder.context.irFactory.buildFun {
name = Name.special("<anonymous>")
returnType = context.irBuiltIns.stringType
visibility = DescriptorVisibilities.LOCAL
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
}.apply {
val bodyBuilder = DeclarationIrBuilder(this@PowerAssertCallTransformer.context, symbol)
body = bodyBuilder.irBlockBody {
+irReturn(message)
}
parent = scope.parent
}
val expression = IrFunctionExpressionImpl(
original.startOffset,
original.endOffset,
messageParameter.type,
lambda,
IrStatementOrigin.LAMBDA
)
irCall(overload, type = original.type).apply {
dispatchReceiver = original.dispatchReceiver?.deepCopyWithSymbols(parent)
extensionReceiver = original.extensionReceiver?.deepCopyWithSymbols(parent)
for (i in 0 until original.typeArgumentsCount) {
putTypeArgument(i, original.getTypeArgument(i))
}
for ((i, argument) in arguments.withIndex()) {
putValueArgument(i, argument?.deepCopyWithSymbols(builder.scope.getLocalDeclarationParent()))
}
putValueArgument(parameters.size - 1, expression)
}
}
}
}
else -> {
null
}
isStringSupertype(messageParameter.type) -> SimpleFunctionDelegate(overload)
isStringFunction(messageParameter.type) -> LambdaFunctionDelegate(overload, messageParameter)
else -> null
}
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power.delegate
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.parent
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
interface FunctionDelegate {
val function: IrFunction
fun buildCall(
builder: IrBuilderWithScope,
original: IrCall,
arguments: List<IrExpression?>,
message: IrExpression
): IrExpression
fun IrBuilderWithScope.irCallCopy(
overload: IrSimpleFunctionSymbol,
original: IrCall,
arguments: List<IrExpression?>,
expression: IrExpression
): IrExpression {
return irCall(overload, type = original.type).apply {
dispatchReceiver = original.dispatchReceiver?.deepCopyWithSymbols(parent)
extensionReceiver = original.extensionReceiver?.deepCopyWithSymbols(parent)
for (i in 0 until original.typeArgumentsCount) {
putTypeArgument(i, original.getTypeArgument(i))
}
for ((i, argument) in arguments.withIndex()) {
putValueArgument(i, argument?.deepCopyWithSymbols(parent))
}
putValueArgument(arguments.size, expression)
}
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power.delegate
import com.bnorm.power.irLambda
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
class LambdaFunctionDelegate(
private val overload: IrSimpleFunctionSymbol,
private val messageParameter: IrValueParameter
) : FunctionDelegate {
override val function = overload.owner
override fun buildCall(
builder: IrBuilderWithScope,
original: IrCall,
arguments: List<IrExpression?>,
message: IrExpression
): IrExpression = with(builder) {
val expression = irLambda(context.irBuiltIns.stringType, messageParameter.type) {
+irReturn(message)
}
irCallCopy(overload, original, arguments, expression)
}
}
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power.delegate
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.parent
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
class SimpleFunctionDelegate(
private val overload: IrSimpleFunctionSymbol
) : FunctionDelegate {
override val function = overload.owner
override fun buildCall(
builder: IrBuilderWithScope,
original: IrCall,
arguments: List<IrExpression?>,
message: IrExpression
): IrExpression = builder.irCallCopy(overload, original, arguments, message)
}
@@ -1,3 +1,19 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power.diagram
import org.jetbrains.kotlin.ir.builders.IrStatementsBuilder
@@ -1,7 +1,58 @@
/*
* Copyright (C) 2020 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irString
import org.jetbrains.kotlin.ir.builders.parent
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.Name
fun IrBuilderWithScope.irString(builderAction: StringBuilder.() -> Unit) =
irString(buildString { builderAction() })
fun IrBuilderWithScope.irLambda(
returnType: IrType,
lambdaType: IrType,
startOffset: Int = this.startOffset,
endOffset: Int = this.endOffset,
block: IrBlockBodyBuilder.() -> Unit
): IrFunctionExpression {
val scope = this
val lambda = context.irFactory.buildFun {
name = Name.special("<anonymous>")
this.returnType = returnType
visibility = DescriptorVisibilities.LOCAL
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
}.apply {
val bodyBuilder = DeclarationIrBuilder(context, symbol)
body = bodyBuilder.irBlockBody {
block()
}
parent = scope.parent
}
return IrFunctionExpressionImpl(startOffset, endOffset, lambdaType, lambda, IrStatementOrigin.LAMBDA)
}
@@ -1,3 +1,19 @@
/*
* Copyright (C) 2020 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import org.junit.Test
@@ -1,44 +0,0 @@
package com.bnorm.power
import org.jetbrains.kotlin.name.FqName
import org.junit.Test
class AssertBooleanTest {
@Test
fun `test assertTrue transformation`() {
assertMessage(
"""
import kotlin.test.assertTrue
fun main() {
assertTrue(1 != 1)
}""",
"""
Assertion failed
assertTrue(1 != 1)
|
false
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertTrue")))
)
}
@Test
fun `test assertFalse transformation`() {
assertMessage(
"""
import kotlin.test.assertFalse
fun main() {
assertFalse(1 == 1)
}""",
"""
Assertion failed
assertFalse(1 == 1)
|
true
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertFalse")))
)
}
}
@@ -0,0 +1,180 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import org.jetbrains.kotlin.name.FqName
import org.junit.Test
class AssertLibraryTest {
@Test
fun `test assertTrue transformation`() {
assertMessage(
"""
import kotlin.test.assertTrue
fun main() {
assertTrue(1 != 1)
}""",
"""
Assertion failed
assertTrue(1 != 1)
|
false
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertTrue")))
)
}
@Test
fun `test assertTrue transformation with message`() {
assertMessage(
"""
import kotlin.test.assertTrue
fun main() {
assertTrue(1 != 1, "Message:")
}""",
"""
Message:
assertTrue(1 != 1, "Message:")
|
false
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertTrue")))
)
}
@Test
fun `test assertFalse transformation`() {
assertMessage(
"""
import kotlin.test.assertFalse
fun main() {
assertFalse(1 == 1)
}""",
"""
Assertion failed
assertFalse(1 == 1)
|
true
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertFalse")))
)
}
@Test
fun `test assertFalse transformation with message`() {
assertMessage(
"""
import kotlin.test.assertFalse
fun main() {
assertFalse(1 == 1, "Message:")
}""",
"""
Message:
assertFalse(1 == 1, "Message:")
|
true
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertFalse")))
)
}
@Test
fun `test assertEquals transformation`() {
assertMessage(
"""
import kotlin.test.assertEquals
fun main() {
val greeting = "Hello"
val name = "World"
assertEquals(greeting, name)
}""",
"""
assertEquals(greeting, name)
| |
| World
Hello expected:<[Hello]> but was:<[World]>
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertEquals")))
)
}
@Test
fun `test assertEquals transformation with message`() {
assertMessage(
"""
import kotlin.test.assertEquals
fun main() {
val greeting = "Hello"
val name = "World"
assertEquals(greeting, name, "Message:")
}""",
"""
Message:
assertEquals(greeting, name, "Message:")
| |
| World
Hello expected:<[Hello]> but was:<[World]>
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertEquals")))
)
}
@Test
fun `test assertNotNull transformation`() {
assertMessage(
"""
import kotlin.test.assertNotNull
fun main() {
val name: String? = null
assertNotNull(name)
}""",
"""
assertNotNull(name)
|
null
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertNotNull")))
)
}
@Test
fun `test assertNotNull transformation with message`() {
assertMessage(
"""
import kotlin.test.assertNotNull
fun main() {
val name: String? = null
assertNotNull(name, "Message:")
}""",
"""
Message:
assertNotNull(name, "Message:")
|
null
""".trimIndent(),
PowerAssertComponentRegistrar(setOf(FqName("kotlin.test.assertNotNull")))
)
}
}
@@ -1,3 +1,19 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import com.tschuchort.compiletesting.KotlinCompilation
@@ -1,3 +1,19 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import com.tschuchort.compiletesting.KotlinCompilation
@@ -1,3 +1,19 @@
/*
* Copyright (C) 2021 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import org.junit.Test
@@ -1,3 +1,19 @@
/*
* Copyright (C) 2020 Brian Norman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bnorm.power
import com.tschuchort.compiletesting.KotlinCompilation