aboutsummaryrefslogtreecommitdiffstats
path: root/build/hv-collector-analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'build/hv-collector-analysis/src')
-rw-r--r--build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsage.kt92
-rw-r--r--build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/VesHvRuleSetProvider.kt36
-rw-r--r--build/hv-collector-analysis/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider1
-rw-r--r--build/hv-collector-analysis/src/main/resources/onap-detekt-config.yml480
-rw-r--r--build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsageTest.kt126
-rw-r--r--build/hv-collector-analysis/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory1
6 files changed, 736 insertions, 0 deletions
diff --git a/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsage.kt b/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsage.kt
new file mode 100644
index 00000000..a070584c
--- /dev/null
+++ b/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsage.kt
@@ -0,0 +1,92 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.analysis
+
+import io.gitlab.arturbosch.detekt.api.CodeSmell
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.Debt
+import io.gitlab.arturbosch.detekt.api.Entity
+import io.gitlab.arturbosch.detekt.api.Issue
+import io.gitlab.arturbosch.detekt.api.Rule
+import io.gitlab.arturbosch.detekt.api.Severity
+import org.jetbrains.kotlin.com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtOperationExpression
+import org.jetbrains.kotlin.psi.KtStringTemplateExpression
+import org.jetbrains.kotlin.psi.KtValueArgumentList
+import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since November 2018
+ */
+class SuboptimalLoggerUsage(config: Config) : Rule(config) {
+
+ override val issue = Issue(javaClass.simpleName,
+ Severity.Performance,
+ """
+ Reports usage of unoptimized logger calls.
+ In Kotlin every method call (including logger calls) is eagerly evaluated by default. That means that
+ each argument will be evaluated even if loglevel is higher than in current call. The most common way of
+ mitigating this issue is to use lazy loading by means of lambda expressions, so instead of
+ log.debug("a=${'$'}a") we can write log.debug{ "a=${'$'}a" }. Logging string literals is fine - no
+ additional computation will be performed.""".trimIndent(),
+ Debt(mins = 10))
+
+ private val loggerNames = config.valueOrDefault("loggerNames", DEFAULT_LOGGER_NAMES).split(",")
+
+ private val loggingMethods = config.valueOrDefault("loggingMethodNames", DEFAULT_LOGGING_METHOD_NAMES).split(",")
+
+ override fun visitCallExpression(expression: KtCallExpression) {
+ val targetObject = expression.parent.firstChild
+ val methodName = expression.firstChild
+
+ logExpressionArguments(targetObject, methodName)
+ ?.let(this::checkGettingWarningMessage)
+ ?.let { reportCodeSmell(expression, it) }
+ }
+
+ private fun logExpressionArguments(targetObject: PsiElement, methodName: PsiElement) =
+ if (isLogExpression(targetObject, methodName))
+ methodName.nextSibling as? KtValueArgumentList
+ else null
+
+ private fun isLogExpression(targetObject: PsiElement, methodName: PsiElement) =
+ loggerNames.any(targetObject::textMatches) && loggingMethods.any(methodName::textMatches)
+
+ private fun checkGettingWarningMessage(args: KtValueArgumentList) = when {
+ args.anyDescendantOfType<KtOperationExpression> { true } ->
+ "should not use any operators in logging expression"
+ args.anyDescendantOfType<KtCallExpression> { true } ->
+ "should not call anything in logging expression"
+ args.anyDescendantOfType<KtStringTemplateExpression> { it.hasInterpolation() } ->
+ "should not use string interpolation in logging expression"
+ else -> null
+ }
+
+ private fun reportCodeSmell(expression: KtCallExpression, message: String) {
+ report(CodeSmell(issue, Entity.from(expression), message))
+ }
+
+ companion object {
+ const val DEFAULT_LOGGER_NAMES = "logger,LOGGER,log,LOG"
+ const val DEFAULT_LOGGING_METHOD_NAMES = "trace,debug,info,warn,error,severe"
+ }
+}
diff --git a/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/VesHvRuleSetProvider.kt b/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/VesHvRuleSetProvider.kt
new file mode 100644
index 00000000..eec933dc
--- /dev/null
+++ b/build/hv-collector-analysis/src/main/kotlin/org/onap/dcae/collectors/veshv/analysis/VesHvRuleSetProvider.kt
@@ -0,0 +1,36 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.analysis
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.RuleSet
+import io.gitlab.arturbosch.detekt.api.RuleSetProvider
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since November 2018
+ */
+class VesHvRuleSetProvider : RuleSetProvider {
+ override val ruleSetId: String
+ get() = "HvVesCustomRules"
+
+ override fun instance(config: Config) = RuleSet(ruleSetId, listOf(SuboptimalLoggerUsage(config)))
+
+}
diff --git a/build/hv-collector-analysis/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider b/build/hv-collector-analysis/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
new file mode 100644
index 00000000..2b26f32f
--- /dev/null
+++ b/build/hv-collector-analysis/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider
@@ -0,0 +1 @@
+org.onap.dcae.collectors.veshv.analysis.VesHvRuleSetProvider \ No newline at end of file
diff --git a/build/hv-collector-analysis/src/main/resources/onap-detekt-config.yml b/build/hv-collector-analysis/src/main/resources/onap-detekt-config.yml
new file mode 100644
index 00000000..f705d36c
--- /dev/null
+++ b/build/hv-collector-analysis/src/main/resources/onap-detekt-config.yml
@@ -0,0 +1,480 @@
+autoCorrect: true
+failFast: false
+
+test-pattern: # Configure exclusions for test sources
+ active: true
+ patterns: # Test file regexes
+ - '.*/test/.*'
+ - '.*Test.kt'
+ - '.*Spec.kt'
+ exclude-rule-sets:
+ - 'comments'
+ exclude-rules:
+ - 'NamingRules'
+ - 'WildcardImport'
+ - 'MagicNumber'
+ - 'MaxLineLength'
+ - 'LateinitUsage'
+ - 'StringLiteralDuplication'
+ - 'SpreadOperator'
+ - 'TooManyFunctions'
+ - 'ForEachOnRange'
+
+build:
+ maxIssues: 3
+ weights:
+ # complexity: 2
+ # LongParameterList: 1
+ # style: 1
+ # comments: 1
+
+processors:
+ active: true
+ exclude:
+ # - 'FunctionCountProcessor'
+ # - 'PropertyCountProcessor'
+ # - 'ClassCountProcessor'
+ # - 'PackageCountProcessor'
+ # - 'KtFileCountProcessor'
+
+console-reports:
+ active: true
+ exclude:
+ # - 'ProjectStatisticsReport'
+ # - 'ComplexityReport'
+ # - 'NotificationReport'
+ # - 'FindingsReport'
+ # - 'BuildFailureReport'
+
+output-reports:
+ active: true
+ exclude:
+ # - 'HtmlOutputReport'
+ # - 'PlainOutputReport'
+ # - 'XmlOutputReport'
+
+comments:
+ active: true
+ CommentOverPrivateFunction:
+ active: false
+ CommentOverPrivateProperty:
+ active: false
+ EndOfSentenceFormat:
+ active: false
+ endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$)
+ UndocumentedPublicClass:
+ active: false
+ searchInNestedClass: true
+ searchInInnerClass: true
+ searchInInnerObject: true
+ searchInInnerInterface: true
+ UndocumentedPublicFunction:
+ active: false
+
+complexity:
+ active: true
+ ComplexCondition:
+ active: true
+ threshold: 4
+ ComplexInterface:
+ active: false
+ threshold: 10
+ includeStaticDeclarations: false
+ ComplexMethod:
+ active: true
+ threshold: 10
+ ignoreSingleWhenExpression: false
+ LabeledExpression:
+ active: false
+ LargeClass:
+ active: true
+ threshold: 150
+ LongMethod:
+ active: true
+ threshold: 20
+ LongParameterList:
+ active: true
+ threshold: 6
+ ignoreDefaultParameters: false
+ MethodOverloading:
+ active: false
+ threshold: 6
+ NestedBlockDepth:
+ active: true
+ threshold: 4
+ StringLiteralDuplication:
+ active: false
+ threshold: 3
+ ignoreAnnotation: true
+ excludeStringsWithLessThan5Characters: true
+ ignoreStringsRegex: '$^'
+ TooManyFunctions:
+ active: true
+ thresholdInFiles: 11
+ thresholdInClasses: 11
+ thresholdInInterfaces: 11
+ thresholdInObjects: 11
+ thresholdInEnums: 11
+ ignoreDeprecated: false
+
+empty-blocks:
+ active: true
+ EmptyCatchBlock:
+ active: true
+ allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
+ EmptyClassBlock:
+ active: true
+ EmptyDefaultConstructor:
+ active: true
+ EmptyDoWhileBlock:
+ active: true
+ EmptyElseBlock:
+ active: true
+ EmptyFinallyBlock:
+ active: true
+ EmptyForBlock:
+ active: true
+ EmptyFunctionBlock:
+ active: true
+ ignoreOverriddenFunctions: false
+ EmptyIfBlock:
+ active: true
+ EmptyInitBlock:
+ active: true
+ EmptyKtFile:
+ active: true
+ EmptySecondaryConstructor:
+ active: true
+ EmptyWhenBlock:
+ active: true
+ EmptyWhileBlock:
+ active: true
+
+exceptions:
+ active: true
+ ExceptionRaisedInUnexpectedLocation:
+ active: false
+ methodNames: 'toString,hashCode,equals,finalize'
+ InstanceOfCheckForException:
+ active: false
+ NotImplementedDeclaration:
+ active: false
+ PrintStackTrace:
+ active: false
+ RethrowCaughtException:
+ active: false
+ ReturnFromFinally:
+ active: false
+ SwallowedException:
+ active: false
+ ThrowingExceptionFromFinally:
+ active: false
+ ThrowingExceptionInMain:
+ active: false
+ ThrowingExceptionsWithoutMessageOrCause:
+ active: false
+ exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
+ ThrowingNewInstanceOfSameException:
+ active: false
+ TooGenericExceptionCaught:
+ active: true
+ exceptionNames:
+ - ArrayIndexOutOfBoundsException
+ - Error
+ - Exception
+ - IllegalMonitorStateException
+ - NullPointerException
+ - IndexOutOfBoundsException
+ - RuntimeException
+ - Throwable
+ TooGenericExceptionThrown:
+ active: true
+ exceptionNames:
+ - Error
+ - Exception
+ - Throwable
+ - RuntimeException
+
+formatting:
+ active: true
+ android: false
+ autoCorrect: true
+ ChainWrapping:
+ active: false
+ autoCorrect: true
+ CommentSpacing:
+ active: true
+ autoCorrect: true
+ Filename:
+ active: true
+ FinalNewline:
+ active: true
+ autoCorrect: true
+ ImportOrdering:
+ active: true
+ autoCorrect: true
+ Indentation:
+ active: true
+ autoCorrect: true
+ indentSize: 4
+ continuationIndentSize: 4
+ MaximumLineLength:
+ active: true
+ maxLineLength: 120
+ ModifierOrdering:
+ active: true
+ autoCorrect: true
+ NoBlankLineBeforeRbrace:
+ active: true
+ autoCorrect: true
+ NoConsecutiveBlankLines:
+ active: true
+ autoCorrect: true
+ NoEmptyClassBody:
+ active: true
+ autoCorrect: true
+ NoItParamInMultilineLambda:
+ active: true
+ NoLineBreakAfterElse:
+ active: true
+ autoCorrect: true
+ NoLineBreakBeforeAssignment:
+ active: true
+ autoCorrect: true
+ NoMultipleSpaces:
+ active: true
+ autoCorrect: true
+ NoSemicolons:
+ active: true
+ autoCorrect: true
+ NoTrailingSpaces:
+ active: true
+ autoCorrect: true
+ NoUnitReturn:
+ active: true
+ autoCorrect: true
+ NoUnusedImports:
+ active: true
+ autoCorrect: true
+ NoWildcardImports:
+ active: true
+ autoCorrect: true
+ ParameterListWrapping:
+ active: false
+ autoCorrect: true
+ indentSize: 4
+ SpacingAroundColon:
+ active: true
+ autoCorrect: true
+ SpacingAroundComma:
+ active: true
+ autoCorrect: true
+ SpacingAroundCurly:
+ active: true
+ autoCorrect: true
+ SpacingAroundKeyword:
+ active: true
+ autoCorrect: true
+ SpacingAroundOperators:
+ active: true
+ autoCorrect: true
+ SpacingAroundRangeOperator:
+ active: true
+ autoCorrect: true
+ StringTemplate:
+ active: true
+ autoCorrect: true
+
+naming:
+ active: true
+ ClassNaming:
+ active: true
+ classPattern: '[A-Z$][a-zA-Z0-9$]*'
+ EnumNaming:
+ active: true
+ enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
+ ForbiddenClassName:
+ active: false
+ forbiddenName: ''
+ FunctionMaxLength:
+ active: false
+ maximumFunctionNameLength: 30
+ FunctionMinLength:
+ active: false
+ minimumFunctionNameLength: 3
+ FunctionNaming:
+ active: true
+ functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
+ excludeClassPattern: '$^'
+ MatchingDeclarationName:
+ active: false
+ MemberNameEqualsClassName:
+ active: false
+ ignoreOverriddenFunction: true
+ ObjectPropertyNaming:
+ active: true
+ propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
+ constantPattern: '[A-Za-z][_A-Za-z0-9]*'
+ PackageNaming:
+ active: true
+ packagePattern: '^[a-z]+(\.[a-z][a-z0-9]*)*$'
+ TopLevelPropertyNaming:
+ active: true
+ constantPattern: '[A-Z][_A-Z0-9]*'
+ propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
+ privatePropertyPattern: '(_)?[A-Za-z][A-Za-z0-9]*'
+ VariableMaxLength:
+ active: false
+ maximumVariableNameLength: 64
+ VariableMinLength:
+ active: false
+ minimumVariableNameLength: 1
+ VariableNaming:
+ active: true
+ variablePattern: '[a-z][A-Za-z0-9]*'
+ privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
+ excludeClassPattern: '$^'
+
+performance:
+ active: true
+ ForEachOnRange:
+ active: true
+ SpreadOperator:
+ active: true
+ UnnecessaryTemporaryInstantiation:
+ active: true
+
+potential-bugs:
+ active: true
+ DuplicateCaseInWhenExpression:
+ active: true
+ EqualsAlwaysReturnsTrueOrFalse:
+ active: false
+ EqualsWithHashCodeExist:
+ active: true
+ ExplicitGarbageCollectionCall:
+ active: true
+ InvalidRange:
+ active: false
+ IteratorHasNextCallsNextMethod:
+ active: false
+ IteratorNotThrowingNoSuchElementException:
+ active: false
+ LateinitUsage:
+ active: false
+ excludeAnnotatedProperties: ""
+ ignoreOnClassesPattern: ""
+ UnconditionalJumpStatementInLoop:
+ active: false
+ UnreachableCode:
+ active: true
+ UnsafeCallOnNullableType:
+ active: false
+ UnsafeCast:
+ active: false
+ UselessPostfixExpression:
+ active: false
+ WrongEqualsTypeParameter:
+ active: false
+
+style:
+ active: true
+ CollapsibleIfStatements:
+ active: false
+ DataClassContainsFunctions:
+ active: false
+ conversionFunctionPrefix: 'to'
+ EqualsNullCall:
+ active: false
+ ExpressionBodySyntax:
+ active: false
+ ForbiddenComment:
+ active: true
+ values: 'TODO:,FIXME:,STOPSHIP:'
+ ForbiddenImport:
+ active: false
+ imports: ''
+ FunctionOnlyReturningConstant:
+ active: false
+ ignoreOverridableFunction: true
+ excludedFunctions: 'describeContents'
+ LoopWithTooManyJumpStatements:
+ active: false
+ maxJumpCount: 1
+ MagicNumber:
+ active: true
+ ignoreNumbers: '-1,0,1,2'
+ ignoreHashCodeFunction: false
+ ignorePropertyDeclaration: false
+ ignoreConstantDeclaration: true
+ ignoreCompanionObjectPropertyDeclaration: true
+ ignoreAnnotation: false
+ ignoreNamedArgument: true
+ ignoreEnums: false
+ MaxLineLength:
+ active: true
+ maxLineLength: 120
+ excludePackageStatements: false
+ excludeImportStatements: false
+ excludeCommentStatements: false
+ MayBeConst:
+ active: false
+ ModifierOrder:
+ active: true
+ NestedClassesVisibility:
+ active: false
+ NewLineAtEndOfFile:
+ active: true
+ NoTabs:
+ active: false
+ OptionalAbstractKeyword:
+ active: true
+ OptionalUnit:
+ active: false
+ OptionalWhenBraces:
+ active: false
+ ProtectedMemberInFinalClass:
+ active: false
+ RedundantVisibilityModifierRule:
+ active: false
+ ReturnCount:
+ active: true
+ max: 2
+ excludedFunctions: "equals"
+ SafeCast:
+ active: true
+ SerialVersionUIDInSerializableClass:
+ active: false
+ SpacingBetweenPackageAndImports:
+ active: false
+ ThrowsCount:
+ active: true
+ max: 2
+ TrailingWhitespace:
+ active: false
+ UnnecessaryAbstractClass:
+ active: false
+ UnnecessaryInheritance:
+ active: false
+ UnnecessaryParentheses:
+ active: false
+ UntilInsteadOfRangeTo:
+ active: false
+ UnusedImports:
+ active: false
+ UnusedPrivateMember:
+ active: true
+ allowedNames: "(_.*|ignored|expected)"
+ UseDataClass:
+ active: false
+ excludeAnnotatedClasses: ""
+ UtilityClassWithPublicConstructor:
+ active: false
+ WildcardImport:
+ active: true
+ excludeImports: 'java.util.*,kotlinx.android.synthetic.*'
+
+HvVesCustomRules:
+ active: true
+ SuboptimalLoggerUsage:
+ active: true
diff --git a/build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsageTest.kt b/build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsageTest.kt
new file mode 100644
index 00000000..0a1d658b
--- /dev/null
+++ b/build/hv-collector-analysis/src/test/kotlin/org/onap/dcae/collectors/veshv/analysis/SuboptimalLoggerUsageTest.kt
@@ -0,0 +1,126 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.analysis
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.test.TestConfig
+import io.gitlab.arturbosch.detekt.test.assertThat
+import io.gitlab.arturbosch.detekt.test.compileAndLint
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.xdescribe
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk></piotr.jaszczyk>@nokia.com>
+ * @since November 2018
+ */
+internal class SuboptimalLoggerUsageTest : Spek({
+
+ fun checkPassingCase(code: String, cut: SuboptimalLoggerUsage = SuboptimalLoggerUsage(Config.empty)) {
+ describe(code) {
+ val findings = cut.compileAndLint(CodeSamples.code(code))
+
+ it("should pass") {
+ assertThat(findings).isEmpty()
+ }
+ }
+ }
+
+ fun checkFailingCase(code: String, cut: SuboptimalLoggerUsage = SuboptimalLoggerUsage(Config.empty)) {
+ describe(code) {
+ val findings = cut.compileAndLint(CodeSamples.code(code))
+
+ it("should fail") {
+ assertThat(findings).isNotEmpty()
+ }
+ }
+ }
+
+ describe("passing cases") {
+ checkPassingCase(CodeSamples.noConcatCall)
+ checkPassingCase(CodeSamples.exceptionCall)
+ checkPassingCase(CodeSamples.lambdaCall)
+ checkPassingCase(CodeSamples.lambdaFunctionCall)
+ checkPassingCase(CodeSamples.lambdaExceptionCall)
+ }
+
+
+ describe("failing cases") {
+ checkFailingCase(CodeSamples.plainConcatCall)
+ checkFailingCase(CodeSamples.expansionCall)
+ checkFailingCase(CodeSamples.plainConcatExceptionCall)
+ checkFailingCase(CodeSamples.expansionExceptionCall)
+ }
+
+ describe("custom configuration") {
+ val cut = SuboptimalLoggerUsage(TestConfig(mapOf("loggerNames" to "l,lo", "loggingMethodNames" to "print")))
+ val strangeLogger = """
+ val l = object {
+ fun print(m: String) { }
+ }
+ val lo = l
+ """.trimIndent()
+
+ checkPassingCase(CodeSamples.plainConcatCall, cut)
+
+ checkPassingCase("""
+ $strangeLogger
+ l.print("n")""".trimIndent(), cut)
+
+ checkFailingCase("""
+ $strangeLogger
+ l.print("n=" + n)""".trimIndent(), cut)
+
+ checkFailingCase("""
+ $strangeLogger
+ lo.print("n=${'$'}n")""".trimIndent(), cut)
+ }
+})
+
+object CodeSamples {
+ private val codeBefore = """
+ object logger {
+ fun debug(msg: String) { println(msg) }
+ fun debug(msg: String, ex: Throwable) { println(msg + ". Cause: " + ex) }
+ fun debug(msg: () -> String) { println(msg()) }
+ fun debug(ex: Throwable, msg: () -> String) { println(msg() + ". Cause: " + ex) }
+ }
+
+ fun execute(n: Integer) {
+ val ex = Exception()
+
+ """.trimIndent()
+ private const val codeAfter = """}"""
+
+ const val noConcatCall = """logger.debug("Executing...")"""
+ const val exceptionCall = """logger.debug("Fail", ex)"""
+ const val lambdaCall = """logger.debug{ "n=${'$'}n" }"""
+ const val lambdaFunctionCall = """logger.debug { n.toString() }"""
+ const val lambdaExceptionCall = """logger.debug(ex) { "epic fail on n=" + n }"""
+
+ const val plainConcatCall = """logger.debug("n=" + n)"""
+ const val expansionCall = """logger.debug("n=${'$'}n")"""
+ const val plainConcatExceptionCall = """logger.debug("Fail. n=" + n, ex)"""
+ const val expansionExceptionCall = """logger.debug("Fail. n=${'$'}n", ex)"""
+
+
+ fun code(core: String) = codeBefore + core + codeAfter
+} \ No newline at end of file
diff --git a/build/hv-collector-analysis/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory b/build/hv-collector-analysis/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 00000000..f8f59003
--- /dev/null
+++ b/build/hv-collector-analysis/src/test/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory \ No newline at end of file