From c92c7e9c73ba8af708f52e29a0fd25758ea0d393 Mon Sep 17 00:00:00 2001 From: "Jack C. Viers" Date: Wed, 16 Aug 2023 22:18:35 -0500 Subject: [PATCH 1/3] Prevents jvm incompat dataclass constructors with value class params * To prevent issues like #275, dataclasses must not use parameters that are value classes without a `JvmStatic` factory method in their companion object. --- config/detekt/detekt.yml | 791 ++++++++++++++++++ core/build.gradle.kts | 28 +- detekt-rules/build.gradle.kts | 40 + .../org/example/detekt/JvmInlineAnnotation.kt | 45 + ...DataClassConstructorWithValueParameters.kt | 98 +++ .../org/example/detekt/XefRuleSetProvider.kt | 16 + ...tlab.arturbosch.detekt.api.RuleSetProvider | 1 + .../src/main/resources/config/config.yml | 5 + detekt-rules/src/main/resources/logback.xml | 11 + .../example/detekt/JvmInlineAnnotationTest.kt | 32 + ...ClassConstructorWithValueParametersTest.kt | 106 +++ examples/scala/build.gradle.kts | 2 +- filesystem/build.gradle.kts | 112 +-- gpt4all-kotlin/build.gradle.kts | 150 ++-- gradle/libs.versions.toml | 4 + integrations/gcp/build.gradle.kts | 34 +- integrations/lucene/build.gradle.kts | 31 +- integrations/pdf/build.gradle.kts | 31 +- integrations/postgresql/build.gradle.kts | 31 +- integrations/sql/build.gradle.kts | 23 +- kotlin-loom/build.gradle.kts | 81 +- kotlin/build.gradle.kts | 147 ++-- openai/build.gradle.kts | 293 ++++--- reasoning/build.gradle.kts | 276 +++--- scala/build.gradle.kts | 2 +- settings.gradle.kts | 7 + tokenizer/build.gradle.kts | 136 +-- 27 files changed, 1921 insertions(+), 612 deletions(-) create mode 100644 config/detekt/detekt.yml create mode 100644 detekt-rules/build.gradle.kts create mode 100644 detekt-rules/src/main/kotlin/org/example/detekt/JvmInlineAnnotation.kt create mode 100644 detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt create mode 100644 detekt-rules/src/main/kotlin/org/example/detekt/XefRuleSetProvider.kt create mode 100644 detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider create mode 100644 detekt-rules/src/main/resources/config/config.yml create mode 100644 detekt-rules/src/main/resources/logback.xml create mode 100644 detekt-rules/src/test/kotlin/org/example/detekt/JvmInlineAnnotationTest.kt create mode 100644 detekt-rules/src/test/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParametersTest.kt diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml new file mode 100644 index 000000000..07f40ebe4 --- /dev/null +++ b/config/detekt/detekt.yml @@ -0,0 +1,791 @@ +build: + maxIssues: 0 + excludeCorrectable: false + weights: + # complexity: 2 + # LongParameterList: 1 + # style: 1 + # comments: 1 + +config: + validation: true + warningsAsErrors: false + checkExhaustiveness: false + # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]' + excludes: '' + +processors: + active: true + exclude: + - 'DetektProgressListener' + # - 'KtFileCountProcessor' + # - 'PackageCountProcessor' + # - 'ClassCountProcessor' + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ProjectComplexityProcessor' + # - 'ProjectCognitiveComplexityProcessor' + # - 'ProjectLLOCProcessor' + # - 'ProjectCLOCProcessor' + # - 'ProjectLOCProcessor' + # - 'ProjectSLOCProcessor' + # - 'LicenseHeaderLoaderExtension' + +console-reports: + active: true + exclude: + - 'ProjectStatisticsReport' + - 'ComplexityReport' + - 'NotificationReport' + - 'FindingsReport' + - 'FileBasedFindingsReport' + # - 'LiteFindingsReport' + +output-reports: + active: false + exclude: + # - 'TxtOutputReport' + # - 'XmlOutputReport' + # - 'HtmlOutputReport' + # - 'MdOutputReport' + # - 'SarifOutputReport' + +comments: + active: false + AbsentOrWrongFileLicense: + active: false + licenseTemplateFile: 'license.template' + licenseTemplateIsRegex: false + CommentOverPrivateFunction: + active: false + CommentOverPrivateProperty: + active: false + DeprecatedBlockTag: + active: false + EndOfSentenceFormat: + active: false + endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)' + KDocReferencesNonPublicProperty: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + OutdatedDocumentation: + active: false + matchTypeParameters: true + matchDeclarationsOrder: true + allowParamOnConstructorProperties: false + UndocumentedPublicClass: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + searchInNestedClass: true + searchInInnerClass: true + searchInInnerObject: true + searchInInnerInterface: true + searchInProtectedClass: false + UndocumentedPublicFunction: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + searchProtectedFunction: false + UndocumentedPublicProperty: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + searchProtectedProperty: false + +complexity: + active: false + CognitiveComplexMethod: + active: false + threshold: 15 + ComplexCondition: + active: false + threshold: 4 + ComplexInterface: + active: false + threshold: 10 + includeStaticDeclarations: false + includePrivateDeclarations: false + ignoreOverloaded: false + CyclomaticComplexMethod: + active: false + threshold: 15 + ignoreSingleWhenExpression: false + ignoreSimpleWhenEntries: false + ignoreNestingFunctions: false + nestingFunctions: + - 'also' + - 'apply' + - 'forEach' + - 'isNotNull' + - 'ifNull' + - 'let' + - 'run' + - 'use' + - 'with' + LabeledExpression: + active: false + ignoredLabels: [] + LargeClass: + active: false + threshold: 600 + LongMethod: + active: false + threshold: 60 + LongParameterList: + active: false + functionThreshold: 6 + constructorThreshold: 7 + ignoreDefaultParameters: false + ignoreDataClasses: true + ignoreAnnotatedParameter: [] + MethodOverloading: + active: false + threshold: 6 + NamedArguments: + active: false + threshold: 3 + ignoreArgumentsMatchingNames: false + NestedBlockDepth: + active: false + threshold: 4 + NestedScopeFunctions: + active: false + threshold: 1 + functions: + - 'kotlin.apply' + - 'kotlin.run' + - 'kotlin.with' + - 'kotlin.let' + - 'kotlin.also' + ReplaceSafeCallChainWithRun: + active: false + StringLiteralDuplication: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + threshold: 3 + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + TooManyFunctions: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + thresholdInFiles: 11 + thresholdInClasses: 11 + thresholdInInterfaces: 11 + thresholdInObjects: 11 + thresholdInEnums: 11 + ignoreDeprecated: false + ignorePrivate: false + ignoreOverridden: false + +coroutines: + active: false + GlobalCoroutineUsage: + active: false + InjectDispatcher: + active: false + dispatcherNames: + - 'IO' + - 'Default' + - 'Unconfined' + RedundantSuspendModifier: + active: false + SleepInsteadOfDelay: + active: false + SuspendFunSwallowedCancellation: + active: false + SuspendFunWithCoroutineScopeReceiver: + active: false + SuspendFunWithFlowReturnType: + active: false + +empty-blocks: + active: false + EmptyCatchBlock: + active: false + allowedExceptionNameRegex: '_|(ignore|expected).*' + EmptyClassBlock: + active: false + EmptyDefaultConstructor: + active: false + EmptyDoWhileBlock: + active: false + EmptyElseBlock: + active: false + EmptyFinallyBlock: + active: false + EmptyForBlock: + active: false + EmptyFunctionBlock: + active: false + ignoreOverridden: false + EmptyIfBlock: + active: false + EmptyInitBlock: + active: false + EmptyKtFile: + active: false + EmptySecondaryConstructor: + active: false + EmptyTryBlock: + active: false + EmptyWhenBlock: + active: false + EmptyWhileBlock: + active: false + +exceptions: + active: false + ExceptionRaisedInUnexpectedLocation: + active: false + methodNames: + - 'equals' + - 'finalize' + - 'hashCode' + - 'toString' + InstanceOfCheckForException: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + NotImplementedDeclaration: + active: false + ObjectExtendsThrowable: + active: false + PrintStackTrace: + active: false + RethrowCaughtException: + active: false + ReturnFromFinally: + active: false + ignoreLabeled: false + SwallowedException: + active: false + ignoredExceptionTypes: + - 'InterruptedException' + - 'MalformedURLException' + - 'NumberFormatException' + - 'ParseException' + allowedExceptionNameRegex: '_|(ignore|expected).*' + ThrowingExceptionFromFinally: + active: false + ThrowingExceptionInMain: + active: false + ThrowingExceptionsWithoutMessageOrCause: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + exceptions: + - 'ArrayIndexOutOfBoundsException' + - 'Exception' + - 'IllegalArgumentException' + - 'IllegalMonitorStateException' + - 'IllegalStateException' + - 'IndexOutOfBoundsException' + - 'NullPointerException' + - 'RuntimeException' + - 'Throwable' + ThrowingNewInstanceOfSameException: + active: false + TooGenericExceptionCaught: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + exceptionNames: + - 'ArrayIndexOutOfBoundsException' + - 'Error' + - 'Exception' + - 'IllegalMonitorStateException' + - 'IndexOutOfBoundsException' + - 'NullPointerException' + - 'RuntimeException' + - 'Throwable' + allowedExceptionNameRegex: '_|(ignore|expected).*' + TooGenericExceptionThrown: + active: false + exceptionNames: + - 'Error' + - 'Exception' + - 'RuntimeException' + - 'Throwable' + +naming: + active: false + BooleanPropertyNaming: + active: false + allowedPattern: '^(is|has|are)' + ClassNaming: + active: false + classPattern: '[A-Z][a-zA-Z0-9]*' + ConstructorParameterNaming: + active: false + parameterPattern: '[a-z][A-Za-z0-9]*' + privateParameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + EnumNaming: + active: false + enumEntryPattern: '[A-Z][_a-zA-Z0-9]*' + ForbiddenClassName: + active: false + forbiddenName: [] + FunctionMaxLength: + active: false + maximumFunctionNameLength: 30 + FunctionMinLength: + active: false + minimumFunctionNameLength: 3 + FunctionNaming: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + functionPattern: '[a-z][a-zA-Z0-9]*' + excludeClassPattern: '$^' + FunctionParameterNaming: + active: false + parameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + InvalidPackageDeclaration: + active: false + rootPackage: '' + requireRootInDeclaration: false + LambdaParameterNaming: + active: false + parameterPattern: '[a-z][A-Za-z0-9]*|_' + MatchingDeclarationName: + active: false + mustBeFirst: true + MemberNameEqualsClassName: + active: false + ignoreOverridden: true + NoNameShadowing: + active: false + NonBooleanPropertyPrefixedWithIs: + active: false + ObjectPropertyNaming: + active: false + constantPattern: '[A-Za-z][_A-Za-z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: false + packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*' + TopLevelPropertyNaming: + active: false + 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: false + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + +performance: + active: false + ArrayPrimitive: + active: false + CouldBeSequence: + active: false + threshold: 3 + ForEachOnRange: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + SpreadOperator: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + UnnecessaryPartOfBinaryExpression: + active: false + UnnecessaryTemporaryInstantiation: + active: false + +potential-bugs: + active: false + AvoidReferentialEquality: + active: false + forbiddenTypePatterns: + - 'kotlin.String' + CastNullableToNonNullableType: + active: false + CastToNullableType: + active: false + Deprecation: + active: false + DontDowncastCollectionTypes: + active: false + DoubleMutabilityForCollection: + active: false + mutableTypes: + - 'kotlin.collections.MutableList' + - 'kotlin.collections.MutableMap' + - 'kotlin.collections.MutableSet' + - 'java.util.ArrayList' + - 'java.util.LinkedHashSet' + - 'java.util.HashSet' + - 'java.util.LinkedHashMap' + - 'java.util.HashMap' + ElseCaseInsteadOfExhaustiveWhen: + active: false + ignoredSubjectTypes: [] + EqualsAlwaysReturnsTrueOrFalse: + active: false + EqualsWithHashCodeExist: + active: false + ExitOutsideMain: + active: false + ExplicitGarbageCollectionCall: + active: false + HasPlatformType: + active: false + IgnoredReturnValue: + active: false + restrictToConfig: true + returnValueAnnotations: + - 'CheckResult' + - '*.CheckResult' + - 'CheckReturnValue' + - '*.CheckReturnValue' + ignoreReturnValueAnnotations: + - 'CanIgnoreReturnValue' + - '*.CanIgnoreReturnValue' + returnValueTypes: + - 'kotlin.sequences.Sequence' + - 'kotlinx.coroutines.flow.*Flow' + - 'java.util.stream.*Stream' + ignoreFunctionCall: [] + ImplicitDefaultLocale: + active: false + ImplicitUnitReturnType: + active: false + allowExplicitReturnType: true + InvalidRange: + active: false + IteratorHasNextCallsNextMethod: + active: false + IteratorNotThrowingNoSuchElementException: + active: false + LateinitUsage: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + ignoreOnClassesPattern: '' + MapGetWithNotNullAssertionOperator: + active: false + MissingPackageDeclaration: + active: false + excludes: ['**/*.kts'] + NullCheckOnMutableProperty: + active: false + NullableToStringCall: + active: false + PropertyUsedBeforeDeclaration: + active: false + UnconditionalJumpStatementInLoop: + active: false + UnnecessaryNotNullCheck: + active: false + UnnecessaryNotNullOperator: + active: false + UnnecessarySafeCall: + active: false + UnreachableCatchBlock: + active: false + UnreachableCode: + active: false + UnsafeCallOnNullableType: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**'] + UnsafeCast: + active: false + UnusedUnaryOperator: + active: false + UselessPostfixExpression: + active: false + WrongEqualsTypeParameter: + active: false + +style: + active: false + AlsoCouldBeApply: + active: false + BracesOnIfStatements: + active: false + singleLine: 'never' + multiLine: 'always' + BracesOnWhenStatements: + active: false + singleLine: 'necessary' + multiLine: 'consistent' + CanBeNonNullable: + active: false + CascadingCallWrapping: + active: false + includeElvis: true + ClassOrdering: + active: false + CollapsibleIfStatements: + active: false + DataClassContainsFunctions: + active: false + conversionFunctionPrefix: + - 'to' + allowOperators: false + DataClassShouldBeImmutable: + active: false + DestructuringDeclarationWithTooManyEntries: + active: false + maxDestructuringEntries: 3 + DoubleNegativeLambda: + active: false + negativeFunctions: + - reason: 'Use `takeIf` instead.' + value: 'takeUnless' + - reason: 'Use `all` instead.' + value: 'none' + negativeFunctionNameParts: + - 'not' + - 'non' + EqualsNullCall: + active: false + EqualsOnSignatureLine: + active: false + ExplicitCollectionElementAccessMethod: + active: false + ExplicitItLambdaParameter: + active: false + ExpressionBodySyntax: + active: false + includeLineWrapping: false + ForbiddenAnnotation: + active: false + annotations: + - reason: 'it is a java annotation. Use `Suppress` instead.' + value: 'java.lang.SuppressWarnings' + - reason: 'it is a java annotation. Use `kotlin.Deprecated` instead.' + value: 'java.lang.Deprecated' + - reason: 'it is a java annotation. Use `kotlin.annotation.MustBeDocumented` instead.' + value: 'java.lang.annotation.Documented' + - reason: 'it is a java annotation. Use `kotlin.annotation.Target` instead.' + value: 'java.lang.annotation.Target' + - reason: 'it is a java annotation. Use `kotlin.annotation.Retention` instead.' + value: 'java.lang.annotation.Retention' + - reason: 'it is a java annotation. Use `kotlin.annotation.Repeatable` instead.' + value: 'java.lang.annotation.Repeatable' + - reason: 'Kotlin does not support @Inherited annotation, see https://youtrack.jetbrains.com/issue/KT-22265' + value: 'java.lang.annotation.Inherited' + ForbiddenComment: + active: false + comments: + - reason: 'Forbidden FIXME todo marker in comment, please fix the problem.' + value: 'FIXME:' + - reason: 'Forbidden STOPSHIP todo marker in comment, please address the problem before shipping the code.' + value: 'STOPSHIP:' + - reason: 'Forbidden TODO todo marker in comment, please do the changes.' + value: 'TODO:' + allowedPatterns: '' + ForbiddenImport: + active: false + imports: [] + forbiddenPatterns: '' + ForbiddenMethodCall: + active: false + methods: + - reason: 'print does not allow you to configure the output stream. Use a logger instead.' + value: 'kotlin.io.print' + - reason: 'println does not allow you to configure the output stream. Use a logger instead.' + value: 'kotlin.io.println' + ForbiddenSuppress: + active: false + rules: [] + ForbiddenVoid: + active: false + ignoreOverridden: false + ignoreUsageInGenerics: false + FunctionOnlyReturningConstant: + active: false + ignoreOverridableFunction: true + ignoreActualFunction: true + excludedFunctions: [] + LoopWithTooManyJumpStatements: + active: false + maxJumpCount: 1 + MagicNumber: + active: false + excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/*.kts'] + ignoreNumbers: + - '-1' + - '0' + - '1' + - '2' + ignoreHashCodeFunction: true + ignorePropertyDeclaration: false + ignoreLocalVariableDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + ignoreRanges: false + ignoreExtensionFunctions: true + MandatoryBracesLoops: + active: false + MaxChainedCallsOnSameLine: + active: false + maxChainedCalls: 5 + MaxLineLength: + active: false + maxLineLength: 120 + excludePackageStatements: true + excludeImportStatements: true + excludeCommentStatements: false + excludeRawStrings: true + MayBeConst: + active: false + ModifierOrder: + active: false + MultilineLambdaItParameter: + active: false + MultilineRawStringIndentation: + active: false + indentSize: 4 + trimmingMethods: + - 'trimIndent' + - 'trimMargin' + NestedClassesVisibility: + active: false + NewLineAtEndOfFile: + active: false + NoTabs: + active: false + NullableBooleanCheck: + active: false + ObjectLiteralToLambda: + active: false + OptionalAbstractKeyword: + active: false + OptionalUnit: + active: false + PreferToOverPairSyntax: + active: false + ProtectedMemberInFinalClass: + active: false + RedundantExplicitType: + active: false + RedundantHigherOrderMapUsage: + active: false + RedundantVisibilityModifierRule: + active: false + ReturnCount: + active: false + max: 2 + excludedFunctions: + - 'equals' + excludeLabeled: false + excludeReturnFromLambda: true + excludeGuardClauses: false + SafeCast: + active: false + SerialVersionUIDInSerializableClass: + active: false + SpacingBetweenPackageAndImports: + active: false + StringShouldBeRawString: + active: false + maxEscapedCharacterCount: 2 + ignoredCharacters: [] + ThrowsCount: + active: false + max: 2 + excludeGuardClauses: false + TrailingWhitespace: + active: false + TrimMultilineRawString: + active: false + trimmingMethods: + - 'trimIndent' + - 'trimMargin' + UnderscoresInNumericLiterals: + active: false + acceptableLength: 4 + allowNonStandardGrouping: false + UnnecessaryAbstractClass: + active: false + UnnecessaryAnnotationUseSiteTarget: + active: false + UnnecessaryApply: + active: false + UnnecessaryBackticks: + active: false + UnnecessaryBracesAroundTrailingLambda: + active: false + UnnecessaryFilter: + active: false + UnnecessaryInheritance: + active: false + UnnecessaryInnerClass: + active: false + UnnecessaryLet: + active: false + UnnecessaryParentheses: + active: false + allowForUnclearPrecedence: false + UntilInsteadOfRangeTo: + active: false + UnusedImports: + active: false + UnusedParameter: + active: false + allowedNames: 'ignored|expected' + UnusedPrivateClass: + active: false + UnusedPrivateMember: + active: false + allowedNames: '' + UnusedPrivateProperty: + active: false + allowedNames: '_|ignored|expected|serialVersionUID' + UseAnyOrNoneInsteadOfFind: + active: false + UseArrayLiteralsInAnnotations: + active: false + UseCheckNotNull: + active: false + UseCheckOrError: + active: false + UseDataClass: + active: false + allowVars: false + UseEmptyCounterpart: + active: false + UseIfEmptyOrIfBlank: + active: false + UseIfInsteadOfWhen: + active: false + ignoreWhenContainingVariableDeclaration: false + UseIsNullOrEmpty: + active: false + UseLet: + active: false + UseOrEmpty: + active: false + UseRequire: + active: false + UseRequireNotNull: + active: false + UseSumOfInsteadOfFlatMapSize: + active: false + UselessCallOnNotNull: + active: false + UtilityClassWithPublicConstructor: + active: false + VarCouldBeVal: + active: false + ignoreLateinitVar: false + WildcardImport: + active: false + excludeImports: + - 'java.util.*' + +XefRuleSet: + JvmInlineAnnotation: + active: true + PublicDataClassConstructorWithValueParameters: + active: true + autocorrect: true diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 2e45edfa2..52756139d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -15,9 +15,14 @@ plugins { alias(libs.plugins.dokka) alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) //id("com.xebia.asfuture").version("0.0.1") } +dependencies { + detektPlugins(project(":detekt-rules")) +} + java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -26,6 +31,13 @@ java { } } +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true +} + kotlin { jvm { compilations { @@ -87,7 +99,7 @@ kotlin { implementation(libs.logback) implementation(libs.skrape) implementation(libs.rss.reader) - api(libs.jackson) + api(libs.jackson) api(libs.jackson.schema) api(libs.jackson.schema.jakarta) api(libs.jakarta.validation) @@ -161,6 +173,20 @@ spotless { } tasks { + + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType().configureEach { maxParallelForks = Runtime.getRuntime().availableProcessors() useJUnitPlatform() diff --git a/detekt-rules/build.gradle.kts b/detekt-rules/build.gradle.kts new file mode 100644 index 000000000..c8d0dadc3 --- /dev/null +++ b/detekt-rules/build.gradle.kts @@ -0,0 +1,40 @@ +@file:Suppress("DSL_SCOPE_VIOLATION") + +repositories { mavenCentral() } + +plugins { + `kotlin-dsl` + base + alias(libs.plugins.spotless) +} + +spotless { + kotlin { + target("**/*.kt") + ktfmt().googleStyle() + } +} + + +dependencies { + api(libs.detekt.api) + testImplementation(libs.detekt.test) + testImplementation(libs.kotest.assertions) + testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") + implementation(libs.klogging) +} + +tasks.withType() { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + +tasks.withType().configureEach { + maxParallelForks = Runtime.getRuntime().availableProcessors() + useJUnitPlatform() + systemProperty("junit.jupiter.testinstance.lifecycle.default", "per_class") + systemProperty("compile-snippet-tests", project.hasProperty("compile-test-snippets")) + testLogging { + setExceptionFormat("full") + setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) + } +} diff --git a/detekt-rules/src/main/kotlin/org/example/detekt/JvmInlineAnnotation.kt b/detekt-rules/src/main/kotlin/org/example/detekt/JvmInlineAnnotation.kt new file mode 100644 index 000000000..bf0edb5f7 --- /dev/null +++ b/detekt-rules/src/main/kotlin/org/example/detekt/JvmInlineAnnotation.kt @@ -0,0 +1,45 @@ +package org.example.detekt + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.CorrectableCodeSmell +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.psi.KtClass + +/** Fixes occurrences of inline data class when enabled to allow for jvm language interop. */ +class JvmInlineAnnotation(config: Config) : Rule(config) { + + override val issue: Issue = + Issue( + javaClass.simpleName, + Severity.Defect, + "This rule reports an public inline value class as incompatible with other jvm languages.", + Debt.FIVE_MINS + ) + + /** + * * Reports inline value classes not marked @JvmInline as a lint warning, and autofixes the + * declaration to include @JvmInline. + */ + override fun visitClass(klass: KtClass) { + + if ( + klass.isValue() && + klass.annotationEntries.filter { e -> e.shortName?.asString() == "JvmInline" }.size < 1 + ) { + report( + CorrectableCodeSmell( + issue, + Entity.from(klass), + "Kotlin inline value classes are not compatible with other jvm lanugages.", + emptyList(), + listOf(Entity.from(klass)), + false + ) + ) + } + } +} diff --git a/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt b/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt new file mode 100644 index 000000000..57e2af98d --- /dev/null +++ b/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt @@ -0,0 +1,98 @@ +package org.example.detekt + +import io.gitlab.arturbosch.detekt.api.* +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtVisitorVoid +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.isValueClassType +import org.jetbrains.kotlin.types.KotlinType + +/** Fixes occurrences of inline data class when enabled to allow for jvm language interop. */ +class PublicDataClassConstructorWithValueParameters(config: Config) : Rule(config) { + + override val issue: Issue = + Issue( + javaClass.simpleName, + Severity.Defect, + "This rule reports public data classes that are incompatible with other jvm languages.", + Debt.FIVE_MINS + ) + + /** * Reports inline value classes not marked @JvmInline as a lint warning. */ + override fun visitClass(ktClass: KtClass) { + try { + if ( + ktClass.isData() && + ktClass.hasPrimaryConstructor() && + ktClass.primaryConstructor?.valueParameters?.any { + val ktpe = bindingContext.get(BindingContext.TYPE, it.typeReference) + + (ktpe as KotlinType).unwrap().isValueClassType() + } == true + ) { + var hasJvmStaticConstructor = false + val hasCompanionObjects = ktClass.companionObjects.isNotEmpty() + if (!hasCompanionObjects) { + hasJvmStaticConstructor = false + } else { + ktClass.companionObjects.forEach { ktObjectDeclaration -> + if (!hasJvmStaticConstructor) { + ktObjectDeclaration.acceptChildren( + object : KtVisitorVoid() { + override fun visitKtElement(element: KtElement) { + try { + element.acceptChildren(this) + } catch (_: UnsupportedOperationException) {} + } + + override fun visitNamedFunction(function: KtNamedFunction) { + if (!hasJvmStaticConstructor) { + val klassParametersAsString = + ktClass.primaryConstructor?.valueParameterList?.parameters?.fold("") { + acc, + parameter -> + if (acc == "") { + acc + parameter.name + ":" + parameter.typeReference?.text + } else { + acc + ", " + parameter.name + ":" + parameter.typeReference?.text + } + } + val functionParametersAsStrings = + function.valueParameterList?.parameters?.fold("") { acc, parameter -> + if (acc == "") { + acc + parameter.name + ":" + parameter.typeReference?.text + } else { + acc + ", " + parameter.name + ":" + parameter.typeReference?.text + } + } + val functionHasJvmStatic = + function.annotationEntries.any { it.shortName?.asString() == "JvmStatic" } + val functionHasAllButLastDefaultConstructorParameter = + klassParametersAsString == functionParametersAsStrings + hasJvmStaticConstructor = + functionHasJvmStatic && functionHasAllButLastDefaultConstructorParameter + } + } + } + ) + } + } + } + if (!hasJvmStaticConstructor) { + report( + CorrectableCodeSmell( + issue, + Entity.from(ktClass), + "Kotlin data classes must have a JVM static factory method to be compatible with other jvm languages.", + emptyList(), + listOf(Entity.from(ktClass)), + true + ) + ) + } + } + } catch (_: Exception) {} + } +} diff --git a/detekt-rules/src/main/kotlin/org/example/detekt/XefRuleSetProvider.kt b/detekt-rules/src/main/kotlin/org/example/detekt/XefRuleSetProvider.kt new file mode 100644 index 000000000..ae0ee5ac7 --- /dev/null +++ b/detekt-rules/src/main/kotlin/org/example/detekt/XefRuleSetProvider.kt @@ -0,0 +1,16 @@ +package org.example.detekt + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.RuleSet +import io.gitlab.arturbosch.detekt.api.RuleSetProvider + +class XefRuleSetProvider : RuleSetProvider { + override val ruleSetId: String = "XefRuleSet" + + override fun instance(config: Config): RuleSet { + return RuleSet( + ruleSetId, + listOf(JvmInlineAnnotation(config), PublicDataClassConstructorWithValueParameters(config)), + ) + } +} diff --git a/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider b/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider new file mode 100644 index 000000000..725c46089 --- /dev/null +++ b/detekt-rules/src/main/resources/META-INF/services/io.gitlab.arturbosch.detekt.api.RuleSetProvider @@ -0,0 +1 @@ +org.example.detekt.XefRuleSetProvider \ No newline at end of file diff --git a/detekt-rules/src/main/resources/config/config.yml b/detekt-rules/src/main/resources/config/config.yml new file mode 100644 index 000000000..49171acad --- /dev/null +++ b/detekt-rules/src/main/resources/config/config.yml @@ -0,0 +1,5 @@ +XefRuleSet: + JvmInlineAnnotation: + active: true + PublicDataClassConstructorWithValueParameters: + active: true \ No newline at end of file diff --git a/detekt-rules/src/main/resources/logback.xml b/detekt-rules/src/main/resources/logback.xml new file mode 100644 index 000000000..4c99ee634 --- /dev/null +++ b/detekt-rules/src/main/resources/logback.xml @@ -0,0 +1,11 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} MDC=%X{user} - %msg%n + + + + + + + \ No newline at end of file diff --git a/detekt-rules/src/test/kotlin/org/example/detekt/JvmInlineAnnotationTest.kt b/detekt-rules/src/test/kotlin/org/example/detekt/JvmInlineAnnotationTest.kt new file mode 100644 index 000000000..509013791 --- /dev/null +++ b/detekt-rules/src/test/kotlin/org/example/detekt/JvmInlineAnnotationTest.kt @@ -0,0 +1,32 @@ +package org.example.detekt + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest +import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext +import io.kotest.matchers.collections.shouldHaveSize +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.junit.jupiter.api.Test + +@KotlinCoreEnvironmentTest +internal class JvmInlineAnnotationTest(private val env: KotlinCoreEnvironment) { + + @Test + fun `reports missing jvminline annotations`() { + val code = """ + value class User(val id: String) + """ + val findings = JvmInlineAnnotation(Config.empty).compileAndLintWithContext(env, code) + findings shouldHaveSize 1 + } + + @Test + fun `doesn't report annotated value classes`() { + val code = + """ + import kotlin.jvm.JvmInline + @JvmInline value class User(val id: String) + """ + val findings = JvmInlineAnnotation(Config.empty).compileAndLintWithContext(env, code) + findings shouldHaveSize 0 + } +} diff --git a/detekt-rules/src/test/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParametersTest.kt b/detekt-rules/src/test/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParametersTest.kt new file mode 100644 index 000000000..fdc7a85c5 --- /dev/null +++ b/detekt-rules/src/test/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParametersTest.kt @@ -0,0 +1,106 @@ +package org.example.detekt + +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest +import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext +import io.kotest.matchers.collections.shouldHaveSize +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.junit.jupiter.api.Test + +@KotlinCoreEnvironmentTest +internal class PublicDataClassConstructorWithValueParametersTest( + private val env: KotlinCoreEnvironment +) { + @Test + fun `reports data classes that have value class parameters without companion static constructor`() { + val code = + """ + import kotlin.jvm.JvmInline + @JvmInline value class Bar(val value: String) + data class Foo(val bar: Bar) + """ + val findings = + PublicDataClassConstructorWithValueParameters(Config.empty) + .compileAndLintWithContext(env, code) + findings.forEach { println(it.message) } + findings shouldHaveSize 1 + } + + @Test + fun `doesn't report data classes with value parameters with companion static constructor`() { + val code = + """ + import kotlin.jvm.JvmInline + import kotlin.jvm.JvmStatic + @JvmInline value class Bar(val value: String) + data class Foo(val bar: Bar) { + companion object { + @JvmStatic + fun apply(bar: Bar): Foo { + return Foo(bar) + } + } + } + """ + val findings = JvmInlineAnnotation(Config.empty).compileAndLintWithContext(env, code) + findings shouldHaveSize 0 + } + + @Test + fun `reports data classes with value parameters with companion objects without static factory methods`() { + val code = + """import kotlin.jvm.JvmInline + @JvmInline value class Bar(val value: String) + data class Foo(val bar: Bar){ + companion object { + val test: String = "test" + fun notAFactoryMethod(): String = test + } + } + """ + val findings = + PublicDataClassConstructorWithValueParameters(Config.empty) + .compileAndLintWithContext(env, code) + findings.forEach { println(it.message) } + findings shouldHaveSize 1 + } + + @Test + fun `reports data classes with value parameters with companion objects with static factory methods that are missing arguments of the targeted class, even if marked JvmStatic`() { + val code = + """import kotlin.jvm.JvmInline + import kotlin.jvm.JvmStatic + @JvmInline value class Bar(val value: String) + data class Foo(val bar: Bar){ + companion object { + val test: Bar = Bar("test") + @JvmStatic fun applyMissingArguments():Foo = Foo(test) + } + } + """ + val findings = + PublicDataClassConstructorWithValueParameters(Config.empty) + .compileAndLintWithContext(env, code) + findings.forEach { println(it.message) } + findings shouldHaveSize 1 + } + + @Test + fun `does not report data classes with value parameters that have static factory methods in their companion objects that have all the arguments of the targeted class that are marked JvmStatic`() { + val code = + """import kotlin.jvm.JvmStatic + import kotlin.jvm.JvmInline + @JvmInline value class Bar(val value: String) + data class Foo(val bar: Bar){ + companion object { + val test: String = "test" + @JvmStatic fun apply(bar: Bar):Foo = Foo(bar) + } + } + """ + val findings = + PublicDataClassConstructorWithValueParameters(Config.empty) + .compileAndLintWithContext(env, code) + findings shouldHaveSize 0 + } +} diff --git a/examples/scala/build.gradle.kts b/examples/scala/build.gradle.kts index 0b1e196a2..8f9010950 100644 --- a/examples/scala/build.gradle.kts +++ b/examples/scala/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { implementation(projects.xefCore) implementation(projects.xefScala) implementation(projects.kotlinLoom) - implementation(projects.xefReasoning) + implementation(projects.xefReasoning) implementation(projects.xefOpenai) implementation(libs.circe.parser) implementation(libs.scala.lang) diff --git a/filesystem/build.gradle.kts b/filesystem/build.gradle.kts index f7af5e56e..fdd5d6061 100644 --- a/filesystem/build.gradle.kts +++ b/filesystem/build.gradle.kts @@ -1,68 +1,78 @@ plugins { - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.kotlinx.serialization) - alias(libs.plugins.spotless) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.spotless) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() +dependencies { detektPlugins(project(":detekt-rules")) } + +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true } +repositories { mavenCentral() } + kotlin { - jvm() - js(IR) { - nodejs() - } + jvm() + js(IR) { nodejs() } - linuxX64() - macosX64() - mingwX64() + linuxX64() + macosX64() + mingwX64() - sourceSets { - val commonMain by getting { - dependencies { - implementation(projects.xefCore) - implementation(libs.okio) - implementation(libs.klogging) - } - } + sourceSets { + val commonMain by getting { + dependencies { + implementation(projects.xefCore) + implementation(libs.okio) + implementation(libs.klogging) + } + } - val jsMain by getting { - dependencies { - implementation(libs.okio.nodefilesystem) - } - } + val jsMain by getting { dependencies { implementation(libs.okio.nodefilesystem) } } - commonTest { - dependencies { - implementation(libs.okio.fakefilesystem) - implementation(libs.kotest.property) - implementation(libs.kotest.framework) - implementation(libs.kotest.assertions) - } - } + commonTest { + dependencies { + implementation(libs.okio.fakefilesystem) + implementation(libs.kotest.property) + implementation(libs.kotest.framework) + implementation(libs.kotest.assertions) + } + } - val jvmTest by getting { - dependencies { - implementation(libs.kotest.junit5) - } - } + val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } } - val linuxX64Main by getting - val macosX64Main by getting - val mingwX64Main by getting + val linuxX64Main by getting + val macosX64Main by getting + val mingwX64Main by getting - create("nativeMain") { - dependsOn(commonMain) - linuxX64Main.dependsOn(this) - macosX64Main.dependsOn(this) - mingwX64Main.dependsOn(this) + create("nativeMain") { + dependsOn(commonMain) + linuxX64Main.dependsOn(this) + macosX64Main.dependsOn(this) + mingwX64Main.dependsOn(this) + } } - } } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType { dependsOn(withType()) } } diff --git a/gpt4all-kotlin/build.gradle.kts b/gpt4all-kotlin/build.gradle.kts index 0a5d1338a..185db9d32 100644 --- a/gpt4all-kotlin/build.gradle.kts +++ b/gpt4all-kotlin/build.gradle.kts @@ -1,93 +1,101 @@ plugins { - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.kotest.multiplatform) - alias(libs.plugins.spotless) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) - alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotest.multiplatform) + alias(libs.plugins.spotless) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() -} +dependencies { detektPlugins(project(":detekt-rules")) } + +repositories { mavenCentral() } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + toolchain { languageVersion = JavaLanguageVersion.of(11) } +} + +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true } kotlin { - jvm { - compilations { - val integrationTest by compilations.creating { - // Create a test task to run the tests produced by this compilation: - tasks.register("integrationTest") { - description = "Run the integration tests" - group = "verification" - classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs - testClassesDirs = output.classesDirs + jvm { + compilations { + val integrationTest by + compilations.creating { + // Create a test task to run the tests produced by this compilation: + tasks.register("integrationTest") { + description = "Run the integration tests" + group = "verification" + classpath = + compileDependencyFiles + + runtimeDependencyFiles + + output.allOutputs + testClassesDirs = output.classesDirs - testLogging { - events("passed") - } + testLogging { events("passed") } + } + } + val test by compilations.getting + integrationTest.associateWith(test) } - } - val test by compilations.getting - integrationTest.associateWith(test) } - } - js(IR) { - browser() - } + js(IR) { browser() } - sourceSets { - val commonMain by getting { - dependencies { - implementation(projects.xefCore) - } - } + sourceSets { + val commonMain by getting { dependencies { implementation(projects.xefCore) } } - commonTest { - dependencies { - implementation(kotlin("test")) - implementation(libs.kotest.property) - implementation(libs.kotest.framework) - implementation(libs.kotest.assertions) - } - } + commonTest { + dependencies { + implementation(kotlin("test")) + implementation(libs.kotest.property) + implementation(libs.kotest.framework) + implementation(libs.kotest.assertions) + } + } - val jvmMain by getting { - dependencies { - implementation(libs.gpt4all.java.bindings) - implementation(libs.ai.djl.huggingface.tokenizers) - } - } + val jvmMain by getting { + dependencies { + implementation(libs.gpt4all.java.bindings) + implementation(libs.ai.djl.huggingface.tokenizers) + } + } - val jsMain by getting { - } + val jsMain by getting {} - val jvmTest by getting { - dependencies { - implementation(libs.kotest.junit5) - } + val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } } } - - } } -tasks.withType().configureEach { - maxParallelForks = Runtime.getRuntime().availableProcessors() - useJUnitPlatform() - testLogging { - setExceptionFormat("full") - setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) - } -} +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType().configureEach { + maxParallelForks = Runtime.getRuntime().availableProcessors() + useJUnitPlatform() + testLogging { + setExceptionFormat("full") + setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) + } + } -tasks.withType { - dependsOn(tasks.withType()) + withType { dependsOn(withType()) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 59970b9be..664b9d60d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,6 +41,7 @@ suspend-transform = "0.3.1" suspendApp = "0.4.0" flyway = "9.17.0" resources-kmp = "0.4.0" +detekt = "1.23.1" [libraries] arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } @@ -108,6 +109,8 @@ jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref jackson-schema = { module = "com.github.victools:jsonschema-generator", version.ref = "jsonschema" } jackson-schema-jakarta = { module = "com.github.victools:jsonschema-module-jakarta-validation", version.ref = "jsonschema" } jakarta-validation = { module = "jakarta.validation:jakarta.validation-api", version.ref = "jakarta" } +detekt-api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" } +detekt-test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" } [bundles] ktor-client = [ @@ -134,3 +137,4 @@ kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest" semver-gradle = { id="com.javiersc.semver", version.ref="semverGradle" } suspend-transform-plugin = { id="love.forte.plugin.suspend-transform", version.ref="suspend-transform" } resources = { id="com.goncalossilva.resources", version.ref="resources-kmp" } +detekt = { id="io.gitlab.arturbosch.detekt", version.ref="detekt"} diff --git a/integrations/gcp/build.gradle.kts b/integrations/gcp/build.gradle.kts index b4f920b81..ebf6ce50d 100644 --- a/integrations/gcp/build.gradle.kts +++ b/integrations/gcp/build.gradle.kts @@ -4,8 +4,22 @@ plugins { alias(libs.plugins.spotless) alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } + +dependencies { + detektPlugins(project(":detekt-rules")) +} + +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../../config/detekt/detekt.yml") + autoCorrect = true +} + + repositories { mavenCentral() } @@ -87,6 +101,22 @@ spotless { } } -tasks.withType { - dependsOn(tasks.withType()) +tasks{ + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType { + dependsOn(withType()) + } + } + diff --git a/integrations/lucene/build.gradle.kts b/integrations/lucene/build.gradle.kts index 1fa90fe9d..a6557f3c8 100644 --- a/integrations/lucene/build.gradle.kts +++ b/integrations/lucene/build.gradle.kts @@ -3,18 +3,24 @@ plugins { id(libs.plugins.kotlinx.serialization.get().pluginId) alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() -} +dependencies { detektPlugins(project(":detekt-rules")) } + +repositories { mavenCentral() } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + toolchain { languageVersion = JavaLanguageVersion.of(11) } +} + +detekt { + toolVersion = "1.23.1" + source = files("src/main/kotlin") + config.setFrom("../../config/detekt/detekt.yml") + autoCorrect = true } dependencies { @@ -23,6 +29,15 @@ dependencies { api(libs.lucene.queries) } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + + withType { dependsOn(withType()) } } diff --git a/integrations/pdf/build.gradle.kts b/integrations/pdf/build.gradle.kts index 26d2fdd7f..2e814686d 100644 --- a/integrations/pdf/build.gradle.kts +++ b/integrations/pdf/build.gradle.kts @@ -2,18 +2,24 @@ plugins { id(libs.plugins.kotlin.jvm.get().pluginId) alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() -} +dependencies { detektPlugins(project(":detekt-rules")) } + +repositories { mavenCentral() } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + toolchain { languageVersion = JavaLanguageVersion.of(11) } +} + +detekt { + toolVersion = "1.23.1" + source = files("src/main/kotlin") + config.setFrom("../../config/detekt/detekt.yml") + autoCorrect = true } dependencies { @@ -23,6 +29,15 @@ dependencies { implementation(libs.ktor.client.cio) } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + + withType { dependsOn(withType()) } } diff --git a/integrations/postgresql/build.gradle.kts b/integrations/postgresql/build.gradle.kts index 8bdd4185c..01c0cf06f 100644 --- a/integrations/postgresql/build.gradle.kts +++ b/integrations/postgresql/build.gradle.kts @@ -3,18 +3,24 @@ plugins { id(libs.plugins.kotlinx.serialization.get().pluginId) alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() -} +dependencies { detektPlugins(project(":detekt-rules")) } + +repositories { mavenCentral() } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + toolchain { languageVersion = JavaLanguageVersion.of(11) } +} + +detekt { + toolVersion = "1.23.1" + source = files("src/main/kotlin") + config.setFrom("../../config/detekt/detekt.yml") + autoCorrect = true } dependencies { @@ -32,6 +38,15 @@ dependencies { testRuntimeOnly(libs.kotest.junit5) } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + + withType { dependsOn(withType()) } } diff --git a/integrations/sql/build.gradle.kts b/integrations/sql/build.gradle.kts index 580b21da2..f66a674cc 100644 --- a/integrations/sql/build.gradle.kts +++ b/integrations/sql/build.gradle.kts @@ -4,8 +4,11 @@ plugins { id(libs.plugins.kotlin.jvm.get().pluginId) alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } +dependencies { detektPlugins(project(":detekt-rules")) } + repositories { mavenCentral() } @@ -18,12 +21,28 @@ java { } } +detekt { + toolVersion = "1.23.1" + source = files("src/main/kotlin") + config.setFrom("../../config/detekt/detekt.yml") + autoCorrect = true +} + dependencies { implementation(projects.xefCore) implementation(projects.xefTokenizer) implementation(libs.klogging) } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + + withType { dependsOn(withType()) } } diff --git a/kotlin-loom/build.gradle.kts b/kotlin-loom/build.gradle.kts index 50a4cf32b..d83f2e753 100644 --- a/kotlin-loom/build.gradle.kts +++ b/kotlin-loom/build.gradle.kts @@ -1,64 +1,67 @@ plugins { - id(libs.plugins.kotlin.jvm.get().pluginId) - alias(libs.plugins.spotless) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) + id(libs.plugins.kotlin.jvm.get().pluginId) + alias(libs.plugins.spotless) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() +dependencies { detektPlugins(project(":detekt-rules")) } + +detekt { + toolVersion = "1.23.1" + source = files("src/main/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true } +repositories { mavenCentral() } + sourceSets { - main { - java.srcDirs("src/main/kotlin") - } - test { - java.srcDirs("src/test/kotlin") - } + main { java.srcDirs("src/main/kotlin") } + test { java.srcDirs("src/test/kotlin") } } java { - sourceCompatibility = JavaVersion.VERSION_19 - targetCompatibility = JavaVersion.VERSION_19 - toolchain { - languageVersion = JavaLanguageVersion.of(19) - } + sourceCompatibility = JavaVersion.VERSION_19 + targetCompatibility = JavaVersion.VERSION_19 + toolchain { languageVersion = JavaLanguageVersion.of(19) } } dependencies { - implementation(libs.kotlinx.coroutines) - testImplementation(kotlin("test")) - testImplementation(libs.assertj) + implementation(libs.kotlinx.coroutines) + testImplementation(kotlin("test")) + testImplementation(libs.assertj) } tasks.withType().configureEach { - options.compilerArgs.addAll( - listOfNotNull( - "--enable-preview", - "--add-modules", "jdk.incubator.concurrent" + options.compilerArgs.addAll( + listOfNotNull("--enable-preview", "--add-modules", "jdk.incubator.concurrent") ) - ) } tasks.withType().configureEach { - useJUnitPlatform() - jvmArgs("--enable-preview", "--add-modules", "jdk.incubator.concurrent") - testLogging { - events("passed", "skipped", "failed") - } + useJUnitPlatform() + jvmArgs("--enable-preview", "--add-modules", "jdk.incubator.concurrent") + testLogging { events("passed", "skipped", "failed") } } spotless { - java { - palantirJavaFormat() - } - kotlin { - target("**/*.kt") - ktfmt().googleStyle() - } + java { palantirJavaFormat() } + kotlin { + target("**/*.kt") + ktfmt().googleStyle() + } } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType { dependsOn(withType()) } } diff --git a/kotlin/build.gradle.kts b/kotlin/build.gradle.kts index 7d921e473..2c49aba70 100644 --- a/kotlin/build.gradle.kts +++ b/kotlin/build.gradle.kts @@ -1,90 +1,109 @@ import org.jetbrains.dokka.gradle.DokkaTask -repositories { - mavenCentral() -} +repositories { mavenCentral() } plugins { - base - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.kotest.multiplatform) - alias(libs.plugins.kotlinx.serialization) - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) + base + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotest.multiplatform) + alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) +} + +dependencies { detektPlugins(project(":detekt-rules")) } + +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + toolchain { languageVersion = JavaLanguageVersion.of(11) } } kotlin { - jvm() - js(IR) { - browser() - nodejs() - } + jvm() + js(IR) { + browser() + nodejs() + } - linuxX64() - macosX64() - macosArm64() - mingwX64() + linuxX64() + macosX64() + macosArm64() + mingwX64() - sourceSets { - val commonMain by getting { - dependencies { - api(projects.xefCore) - api(projects.xefOpenai) - } + sourceSets { + val commonMain by getting { + dependencies { + api(projects.xefCore) + api(projects.xefOpenai) + } + } } - } } spotless { - kotlin { - target("**/*.kt") - ktfmt().googleStyle() - } + kotlin { + target("**/*.kt") + ktfmt().googleStyle() + } } tasks { - withType().configureEach { - maxParallelForks = Runtime.getRuntime().availableProcessors() - useJUnitPlatform() - testLogging { - setExceptionFormat("full") - setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true } - } - - withType().configureEach { - kotlin.sourceSets.forEach { kotlinSourceSet -> - dokkaSourceSets.named(kotlinSourceSet.name) { - perPackageOption { - matchingRegex.set(".*\\.internal.*") - suppress.set(true) + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType().configureEach { + maxParallelForks = Runtime.getRuntime().availableProcessors() + useJUnitPlatform() + testLogging { + setExceptionFormat("full") + setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) } - skipDeprecated.set(true) - reportUndocumented.set(false) - val baseUrl: String = checkNotNull(project.properties["pom.smc.url"]?.toString()) + } + + withType().configureEach { + kotlin.sourceSets.forEach { kotlinSourceSet -> + dokkaSourceSets.named(kotlinSourceSet.name) { + perPackageOption { + matchingRegex.set(".*\\.internal.*") + suppress.set(true) + } + skipDeprecated.set(true) + reportUndocumented.set(false) + val baseUrl: String = checkNotNull(project.properties["pom.smc.url"]?.toString()) - kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> - sourceLink { - localDirectory.set(srcDir) - remoteUrl.set(uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}").toURL()) - remoteLineSuffix.set("#L") - } + kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> + sourceLink { + localDirectory.set(srcDir) + remoteUrl.set( + uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}") + .toURL() + ) + remoteLineSuffix.set("#L") + } + } + } } - } } - } } -tasks.withType { - dependsOn(tasks.withType()) -} +tasks.withType { dependsOn(tasks.withType()) } diff --git a/openai/build.gradle.kts b/openai/build.gradle.kts index 17ad87cf2..20bc75bbe 100644 --- a/openai/build.gradle.kts +++ b/openai/build.gradle.kts @@ -2,187 +2,182 @@ import org.jetbrains.dokka.gradle.DokkaTask -repositories { - mavenCentral() -} +repositories { mavenCentral() } plugins { - base - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.kotest.multiplatform) - alias(libs.plugins.kotlinx.serialization) - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) - //id("com.xebia.asfuture").version("0.0.1") + base + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotest.multiplatform) + alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) + // id("com.xebia.asfuture").version("0.0.1") } +dependencies { detektPlugins(project(":detekt-rules")) } + java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + toolchain { languageVersion = JavaLanguageVersion.of(11) } +} + +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true } kotlin { - jvm { - compilations { - val integrationTest by compilations.creating { - // Create a test task to run the tests produced by this compilation: - tasks.register("integrationTest") { - description = "Run the integration tests" - group = "verification" - classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs - testClassesDirs = output.classesDirs - - testLogging { - events("passed") - } + jvm { + compilations { + val integrationTest by + compilations.creating { + // Create a test task to run the tests produced by this compilation: + tasks.register("integrationTest") { + description = "Run the integration tests" + group = "verification" + classpath = + compileDependencyFiles + + runtimeDependencyFiles + + output.allOutputs + testClassesDirs = output.classesDirs + + testLogging { events("passed") } + } + } + val test by compilations.getting + integrationTest.associateWith(test) } - } - val test by compilations.getting - integrationTest.associateWith(test) } - } - js(IR) { - browser() - nodejs() - } - - linuxX64() - macosX64() - macosArm64() - mingwX64() - - sourceSets { - all { - languageSettings.optIn("kotlin.ExperimentalStdlibApi") + js(IR) { + browser() + nodejs() } - val commonMain by getting { - dependencies { - implementation(projects.xefCore) - implementation(libs.openai.client) - implementation(libs.klogging) - } - } + linuxX64() + macosX64() + macosArm64() + mingwX64() - val commonTest by getting { - dependencies { - implementation(libs.kotest.property) - implementation(libs.kotest.framework) - implementation(libs.kotest.assertions) - } - } + sourceSets { + all { languageSettings.optIn("kotlin.ExperimentalStdlibApi") } - val jvmMain by getting { - dependencies { - implementation(libs.logback) - api(libs.ktor.client.cio) - } - } + val commonMain by getting { + dependencies { + implementation(projects.xefCore) + implementation(libs.openai.client) + implementation(libs.klogging) + } + } - val jvmTest by getting { - dependencies { - implementation(libs.kotest.junit5) - } - } + val commonTest by getting { + dependencies { + implementation(libs.kotest.property) + implementation(libs.kotest.framework) + implementation(libs.kotest.assertions) + } + } - val jsMain by getting { - dependencies { - api(libs.ktor.client.js) - } - } + val jvmMain by getting { + dependencies { + implementation(libs.logback) + api(libs.ktor.client.cio) + } + } - val linuxX64Main by getting { - dependencies { - api(libs.ktor.client.cio) - } - } + val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } } - val macosX64Main by getting { - dependencies { - api(libs.ktor.client.cio) - } - } + val jsMain by getting { dependencies { api(libs.ktor.client.js) } } - val macosArm64Main by getting { - dependencies { - api(libs.ktor.client.cio) - } - } + val linuxX64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val mingwX64Main by getting { - dependencies { - api(libs.ktor.client.winhttp) - } - } + val macosX64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val linuxX64Test by getting - val macosX64Test by getting - val macosArm64Test by getting - val mingwX64Test by getting - - create("nativeMain") { - dependsOn(commonMain) - linuxX64Main.dependsOn(this) - macosX64Main.dependsOn(this) - macosArm64Main.dependsOn(this) - mingwX64Main.dependsOn(this) - } + val macosArm64Main by getting { dependencies { api(libs.ktor.client.cio) } } + + val mingwX64Main by getting { dependencies { api(libs.ktor.client.winhttp) } } + + val linuxX64Test by getting + val macosX64Test by getting + val macosArm64Test by getting + val mingwX64Test by getting + + create("nativeMain") { + dependsOn(commonMain) + linuxX64Main.dependsOn(this) + macosX64Main.dependsOn(this) + macosArm64Main.dependsOn(this) + mingwX64Main.dependsOn(this) + } - create("nativeTest") { - dependsOn(commonTest) - linuxX64Test.dependsOn(this) - macosX64Test.dependsOn(this) - macosArm64Test.dependsOn(this) - mingwX64Test.dependsOn(this) + create("nativeTest") { + dependsOn(commonTest) + linuxX64Test.dependsOn(this) + macosX64Test.dependsOn(this) + macosArm64Test.dependsOn(this) + mingwX64Test.dependsOn(this) + } } - } } spotless { - kotlin { - target("**/*.kt") - ktfmt().googleStyle() - } + kotlin { + target("**/*.kt") + ktfmt().googleStyle() + } } tasks { - withType().configureEach { - maxParallelForks = Runtime.getRuntime().availableProcessors() - useJUnitPlatform() - testLogging { - setExceptionFormat("full") - setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) } - } - - withType().configureEach { - kotlin.sourceSets.forEach { kotlinSourceSet -> - dokkaSourceSets.named(kotlinSourceSet.name) { - perPackageOption { - matchingRegex.set(".*\\.internal.*") - suppress.set(true) + withType().configureEach { + maxParallelForks = Runtime.getRuntime().availableProcessors() + useJUnitPlatform() + testLogging { + setExceptionFormat("full") + setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) } - skipDeprecated.set(true) - reportUndocumented.set(false) - val baseUrl: String = checkNotNull(project.properties["pom.smc.url"]?.toString()) - - kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> - sourceLink { - localDirectory.set(srcDir) - remoteUrl.set(uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}").toURL()) - remoteLineSuffix.set("#L") - } + } + + withType().configureEach { + kotlin.sourceSets.forEach { kotlinSourceSet -> + dokkaSourceSets.named(kotlinSourceSet.name) { + perPackageOption { + matchingRegex.set(".*\\.internal.*") + suppress.set(true) + } + skipDeprecated.set(true) + reportUndocumented.set(false) + val baseUrl: String = checkNotNull(project.properties["pom.smc.url"]?.toString()) + + kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> + sourceLink { + localDirectory.set(srcDir) + remoteUrl.set( + uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}") + .toURL() + ) + remoteLineSuffix.set("#L") + } + } + } } - } } - } } -tasks.withType { - dependsOn(tasks.withType()) -} +tasks.withType { dependsOn(tasks.withType()) } diff --git a/reasoning/build.gradle.kts b/reasoning/build.gradle.kts index 64db97aed..ce103b59e 100644 --- a/reasoning/build.gradle.kts +++ b/reasoning/build.gradle.kts @@ -2,177 +2,173 @@ import org.jetbrains.dokka.gradle.DokkaTask -repositories { - mavenCentral() -} +repositories { mavenCentral() } plugins { - base - id(libs.plugins.kotlin.multiplatform.get().pluginId) - alias(libs.plugins.kotest.multiplatform) - id(libs.plugins.kotlinx.serialization.get().pluginId) - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) - //id("com.xebia.asfuture").version("0.0.1") + base + id(libs.plugins.kotlin.multiplatform.get().pluginId) + alias(libs.plugins.kotest.multiplatform) + id(libs.plugins.kotlinx.serialization.get().pluginId) + alias(libs.plugins.spotless) + alias(libs.plugins.dokka) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.detekt) + // id("com.xebia.asfuture").version("0.0.1") } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + toolchain { languageVersion = JavaLanguageVersion.of(11) } +} + +dependencies { detektPlugins(project(":detekt-rules")) } + +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true } kotlin { - jvm { - compilations { - val integrationTest by compilations.creating { - // Create a test task to run the tests produced by this compilation: - tasks.register("integrationTest") { - description = "Run the integration tests" - group = "verification" - classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs - testClassesDirs = output.classesDirs - - testLogging { - events("passed") - } + jvm { + compilations { + val integrationTest by + compilations.creating { + // Create a test task to run the tests produced by this compilation: + tasks.register("integrationTest") { + description = "Run the integration tests" + group = "verification" + classpath = + compileDependencyFiles + + runtimeDependencyFiles + + output.allOutputs + testClassesDirs = output.classesDirs + + testLogging { events("passed") } + } + } + val test by compilations.getting + integrationTest.associateWith(test) } - } - val test by compilations.getting - integrationTest.associateWith(test) } - } - js(IR) { - browser() - nodejs() - } - - linuxX64() - macosX64() - macosArm64() - mingwX64() - - sourceSets { - all { - languageSettings.optIn("kotlin.ExperimentalStdlibApi") + js(IR) { + browser() + nodejs() } - val commonMain by getting { - dependencies { - implementation(projects.xefCore) - implementation(libs.okio) - implementation(libs.klogging) - implementation(libs.uuid) - implementation(libs.bundles.ktor.client) - } - } + linuxX64() + macosX64() + macosArm64() + mingwX64() + + sourceSets { + all { languageSettings.optIn("kotlin.ExperimentalStdlibApi") } + + val commonMain by getting { + dependencies { + implementation(projects.xefCore) + implementation(libs.okio) + implementation(libs.klogging) + implementation(libs.uuid) + implementation(libs.bundles.ktor.client) + } + } - val commonTest by getting { - dependencies { - implementation(libs.kotest.property) - implementation(libs.kotest.framework) - implementation(libs.kotest.assertions) - } - } + val commonTest by getting { + dependencies { + implementation(libs.kotest.property) + implementation(libs.kotest.framework) + implementation(libs.kotest.assertions) + } + } - val jvmMain by getting { - dependencies { - implementation(libs.logback) - implementation(projects.xefPdf) - implementation(projects.xefFilesystem) - api(libs.ktor.client.cio) - } - } + val jvmMain by getting { + dependencies { + implementation(libs.logback) + implementation(projects.xefPdf) + implementation(projects.xefFilesystem) + api(libs.ktor.client.cio) + } + } - val jsMain by getting { - dependencies { - api(libs.ktor.client.js) - } - } + val jsMain by getting { dependencies { api(libs.ktor.client.js) } } - val jvmTest by getting { - dependencies { - implementation(libs.kotest.junit5) - } - } + val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } } - val linuxX64Main by getting { - dependencies { - api(libs.ktor.client.cio) - } - } + val linuxX64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val macosX64Main by getting { - dependencies { - api(libs.ktor.client.cio) - } - } + val macosX64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val macosArm64Main by getting { - dependencies { - api(libs.ktor.client.cio) - } - } + val macosArm64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val mingwX64Main by getting { - dependencies { - api(libs.ktor.client.winhttp) - } - } + val mingwX64Main by getting { dependencies { api(libs.ktor.client.winhttp) } } - create("nativeMain") { - dependsOn(commonMain) - linuxX64Main.dependsOn(this) - macosX64Main.dependsOn(this) - mingwX64Main.dependsOn(this) + create("nativeMain") { + dependsOn(commonMain) + linuxX64Main.dependsOn(this) + macosX64Main.dependsOn(this) + mingwX64Main.dependsOn(this) + } } - } } spotless { - kotlin { - target("**/*.kt") - ktfmt().googleStyle() - } + kotlin { + target("**/*.kt") + ktfmt().googleStyle() + } } tasks { - withType().configureEach { - maxParallelForks = Runtime.getRuntime().availableProcessors() - useJUnitPlatform() - testLogging { - setExceptionFormat("full") - setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true } - } - - withType().configureEach { - kotlin.sourceSets.forEach { kotlinSourceSet -> - dokkaSourceSets.named(kotlinSourceSet.name) { - perPackageOption { - matchingRegex.set(".*\\.internal.*") - suppress.set(true) + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + + withType().configureEach { + maxParallelForks = Runtime.getRuntime().availableProcessors() + useJUnitPlatform() + testLogging { + setExceptionFormat("full") + setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) } - skipDeprecated.set(true) - reportUndocumented.set(false) - val baseUrl: String = checkNotNull(project.properties["pom.smc.url"]?.toString()) - - kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> - sourceLink { - localDirectory.set(srcDir) - remoteUrl.set(uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}").toURL()) - remoteLineSuffix.set("#L") - } + } + + withType().configureEach { + kotlin.sourceSets.forEach { kotlinSourceSet -> + dokkaSourceSets.named(kotlinSourceSet.name) { + perPackageOption { + matchingRegex.set(".*\\.internal.*") + suppress.set(true) + } + skipDeprecated.set(true) + reportUndocumented.set(false) + val baseUrl: String = checkNotNull(project.properties["pom.smc.url"]?.toString()) + + kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> + sourceLink { + localDirectory.set(srcDir) + remoteUrl.set( + uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}") + .toURL() + ) + remoteLineSuffix.set("#L") + } + } + } } - } } - } } -tasks.withType { - dependsOn(tasks.withType()) -} +tasks.withType { dependsOn(tasks.withType()) } diff --git a/scala/build.gradle.kts b/scala/build.gradle.kts index 0d082b9a8..e9fa958c5 100644 --- a/scala/build.gradle.kts +++ b/scala/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { implementation(projects.xefCore) implementation(projects.xefOpenai) implementation(projects.kotlinLoom) - implementation(libs.kotlinx.coroutines.reactive) + implementation(libs.kotlinx.coroutines.reactive) // TODO split to separate Scala library implementation(projects.xefPdf) diff --git a/settings.gradle.kts b/settings.gradle.kts index c59fdb9c0..2d5fa6035 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -91,3 +91,10 @@ project(":xef-java-examples").projectDir = file("examples/java") // include("xef-server") project(":xef-server").projectDir = file("server") +// + +// +include("detekt-rules") +project(":detekt-rules").projectDir = file("detekt-rules") +// + diff --git a/tokenizer/build.gradle.kts b/tokenizer/build.gradle.kts index 60ea055a7..d0e72fe80 100644 --- a/tokenizer/build.gradle.kts +++ b/tokenizer/build.gradle.kts @@ -1,86 +1,88 @@ plugins { - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.kotest.multiplatform) - alias(libs.plugins.spotless) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) - alias(libs.plugins.resources) + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.kotest.multiplatform) + alias(libs.plugins.spotless) + alias(libs.plugins.arrow.gradle.publish) + alias(libs.plugins.semver.gradle) + alias(libs.plugins.resources) + alias(libs.plugins.detekt) } -repositories { - mavenCentral() -} +dependencies { detektPlugins(project(":detekt-rules")) } + +repositories { mavenCentral() } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - toolchain { - languageVersion = JavaLanguageVersion.of(11) - } + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + toolchain { languageVersion = JavaLanguageVersion.of(11) } } -kotlin { - jvm() - js(IR) { - browser() - nodejs() - } - linuxX64() - macosX64() - macosArm64() - mingwX64() - - sourceSets { - val commonMain by getting +detekt { + toolVersion = "1.23.1" + source = files("src/commonMain/kotlin", "src/jvmMain/kotlin") + config.setFrom("../config/detekt/detekt.yml") + autoCorrect = true +} - commonTest { - dependencies { - implementation(kotlin("test")) - implementation(libs.kotest.property) - implementation(libs.kotest.framework) - implementation(libs.kotest.assertions) - implementation("com.goncalossilva:resources:0.3.2") - } +kotlin { + jvm() + js(IR) { + browser() + nodejs() } + linuxX64() + macosX64() + macosArm64() + mingwX64() - val jvmTest by getting { - dependencies { - implementation(libs.kotest.junit5) - } - } + sourceSets { + val commonMain by getting - js { - nodejs { - testTask { - useMocha { - timeout = "10000" - } + commonTest { + dependencies { + implementation(kotlin("test")) + implementation(libs.kotest.property) + implementation(libs.kotest.framework) + implementation(libs.kotest.assertions) + implementation("com.goncalossilva:resources:0.3.2") + } } - } - browser { - testTask { - useMocha { - timeout = "10000" - } + + val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } } + + js { + nodejs { testTask { useMocha { timeout = "10000" } } } + browser { testTask { useMocha { timeout = "10000" } } } } - } - } - val linuxX64Main by getting - val macosX64Main by getting - val macosArm64Main by getting - val mingwX64Main by getting + val linuxX64Main by getting + val macosX64Main by getting + val macosArm64Main by getting + val mingwX64Main by getting - create("nativeMain") { - dependsOn(commonMain) - linuxX64Main.dependsOn(this) - macosX64Main.dependsOn(this) - macosArm64Main.dependsOn(this) - mingwX64Main.dependsOn(this) + create("nativeMain") { + dependsOn(commonMain) + linuxX64Main.dependsOn(this) + macosX64Main.dependsOn(this) + macosArm64Main.dependsOn(this) + mingwX64Main.dependsOn(this) + } } - } } -tasks.withType { - dependsOn(tasks.withType()) +tasks { + withType().configureEach { + dependsOn(":detekt-rules:assemble") + autoCorrect = true + } + named("detektJvmMain") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + named("detekt") { + dependsOn(":detekt-rules:assemble") + getByName("build").dependsOn(this) + } + withType { dependsOn(withType()) } } From 3a649ebe0f0caa0c12ebbceb66a2ce29f03d27fd Mon Sep 17 00:00:00 2001 From: Jack Viers Date: Thu, 17 Aug 2023 10:01:45 -0500 Subject: [PATCH 2/3] Update detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt --- .../detekt/PublicDataClassConstructorWithValueParameters.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt b/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt index 57e2af98d..e4d48f079 100644 --- a/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt +++ b/detekt-rules/src/main/kotlin/org/example/detekt/PublicDataClassConstructorWithValueParameters.kt @@ -85,7 +85,7 @@ class PublicDataClassConstructorWithValueParameters(config: Config) : Rule(confi CorrectableCodeSmell( issue, Entity.from(ktClass), - "Kotlin data classes must have a JVM static factory method to be compatible with other jvm languages.", + "Kotlin data classes containing parameters that are value classes must have a JVM static factory method to be compatible with other jvm languages.", emptyList(), listOf(Entity.from(ktClass)), true From 4a4b08d5493488824fde5396db79b0bca5d54bfe Mon Sep 17 00:00:00 2001 From: Jack Viers Date: Thu, 17 Aug 2023 15:43:22 -0500 Subject: [PATCH 3/3] Update detekt.yml Bump to trigger workflow --- config/detekt/detekt.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 07f40ebe4..dec720c07 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -6,7 +6,6 @@ build: # LongParameterList: 1 # style: 1 # comments: 1 - config: validation: true warningsAsErrors: false