diff --git a/.gitignore b/.gitignore index f4f3953..b30a8d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .gradle .idea build -out \ No newline at end of file +out diff --git a/README.md b/README.md index e1d3a44..196ff39 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Kotlin source code documentation management tool. -This is a tool that produces Kotlin source example files and tests from markdown documents +This is a tool that produces Kotlin source example files and tests from Markdown documents with embedded snippets of Kotlin code. It also helps to add links to the API documentation website into the documents and has a few other helpful markdown-management features. @@ -20,7 +20,7 @@ which are committed to the VCS. The overall workflow is: 3. Commit to VCS. 4. Generated files are automatically verified on subsequent project builds. -Knit does not really parse markdown format or HTML, but understands certain Knit markup patterns and _directives_. +Knit does not really parse Markdown format or HTML, but understands certain Knit markup patterns and _directives_. Directives in markdown files must always start at the beginning of the line and have the following general format for single-line directives: @@ -158,7 +158,7 @@ file name, for example: The name of the example file must match a specific pattern. By default, this pattern's regex is `example-[a-zA-Z0-9-]+-##\\.kt`. It can be overridden via `knit.pattern` [property](#knit-properties). -The sequence of hashes (`#`) in the pattern matches any alpha-numeric sequence and causes the examples to +The sequence of hashes (`#`) in the pattern matches any alphanumeric sequence and causes the examples to be automatically consecutively numbered inside the markdown file. For example, you can add a new section of code at the beginning of the document and write in the markdown file: @@ -183,7 +183,7 @@ fun foo() {} A `KNIT` directive can be used to trigger generation of an example file instead of providing a readable reference to a file. In this case, only an example file name shall be specified (without a path). An example file will be written to the `knit.dir` [property](#knit-properties) directory. -The name of the file shall still match the `knit.pattern` [property](#knit-properties) pattern and +The name of the file shall still match the `knit.pattern` [property](#knit-properties) pattern, and it will be automatically numbered as explained in the previous section. For example: @@ -195,7 +195,7 @@ For example: #### Merging code pieces -All tripple-backquoted Kotlin sections are merged together and are output to the Kotlin source file when the next +All triple-backquoted Kotlin sections are merged together and are output to the Kotlin source file when the next Knit pattern in encountered. This way, documentation can be written fluently, explaining functions as they are introduced. For example, the following markdown: @@ -289,7 +289,7 @@ A single piece of code can be included into multiple examples (as opposed to the by specifying regex pattern of the example file name right after the `INCLUDE` directive as its parameter. With the pattern the `INCLUDE` directive can also be specified on a single line, without the -code inside of it. In this case, the code to be included is taken from the previously tripple-backquoted +code inside it. In this case, the code to be included is taken from the previously triple-backquoted Kotlin source code before it. This way, the code snippet can be introduced and shown to the reader of the documentation and then included into the several subsequent examples. @@ -362,7 +362,7 @@ test.package=com.example.test Here `test.dir` specified the directory where the Kotlin test code is generated too and `test.package` specifies the package. In the beginning of the markdown file you specify the name of the test using `TEST_NAME` directive. There is one test file per the source markdown file with a test-case for each example. After the example -you can place the expected output of the test in tripple-quoted `text` block and add `TEST` directive after +you can place the expected output of the test in triple-quoted `text` block and add `TEST` directive after it to get the test-case added. For example: @@ -446,7 +446,7 @@ The names of the modes are mapped to comparison functions via `test.mode. { - kotlinOptions.apply { - languageVersion = "1.4" - jvmTarget = "1.8" - allWarningsAsErrors = true - freeCompilerArgs = freeCompilerArgs + listOf("-Xsuppress-version-warnings") // suppress deprecated 1.4 - } - } - - sourceSets { - main.kotlin.dir = "src" - test.kotlin.dir = "test" - main.resources.dir = "resources" - } - - // Set version when deploying - properties["DeployVersion"]?.let { version = it } -} - -publishing { - publications { - create("maven") { - from(components["java"]) - mavenCentralArtifacts(project, project.sourceSets.main.allSource) - } - } - mavenCentralMetadata() - mavenRepositoryPublishing(project) - publications.withType(MavenPublication::class).all { - signPublicationIfKeyPresent(this) - } -} - -// ---------- This root project -- Gradle plugin ---------- - -apply(plugin = "org.gradle.java-gradle-plugin") -apply(plugin = "com.gradle.plugin-publish") - -extensions.getByType(PluginBundleExtension::class).apply { - website = "https://github.com/Kotlin/kotlinx-knit" - vcsUrl = "https://github.com/Kotlin/kotlinx-knit" - tags = listOf("kotlin", "documentation", "markdown") -} - -gradlePlugin { - plugins { - create("kotlinx-knit") { - // This is a fully-qualified plugin id, short id of 'kotlinx-knit' is added manually in resources - id = "org.jetbrains.kotlinx.knit" - implementationClass = "kotlinx.knit.KnitPlugin" - displayName = "Knit documentation plugin" - description = "Produces Kotlin source example files and tests from markdown documents with embedded snippets of Kotlin code" - } - } -} - -val publishPlugins by tasks.getting(PublishTask::class) - -val deploy: Task by tasks.creating { - dependsOn(getTasksByName("publish", true)) - dependsOn(publishPlugins) -} - -val freemarkerVersion: String by project -val dokkaVersion: String by project - -dependencies { - implementation(gradleApi()) - implementation(project(":pathsaver")) - implementation("org.freemarker:freemarker:$freemarkerVersion") - implementation(project(":kotlinx-knit-test")) - implementation("org.jetbrains.dokka:dokka-core:$dokkaVersion") + buildsrc.conventions.base } -val test: Task by tasks.getting { - dependsOn(tasks.findByPath(":kotlinx-knit-test:dokka")) - dependsOn(tasks.findByPath(":kotlinx-knit-test:dokkaHtml")) -} +group = "kotlinx.knit" +version = "0.4.0-SNAPSHOT" diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index d2aab21..36f9869 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,30 +1,36 @@ /* * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jetbrains.kotlin.gradle.plugin.* import java.util.* plugins { `kotlin-dsl` + kotlin("jvm") version embeddedKotlinVersion } -repositories { - mavenCentral() -} - -val props = Properties().apply { - project.file("../gradle.properties").inputStream().use { load(it) } +dependencies { + implementation(platform(libs.kotlin.bom)) + implementation(libs.gradlePlugin.kotlin) + implementation(libs.gradlePlugin.dokka) + implementation(libs.gradlePlugin.gradlePluginPublish) } -val kotlinVersion: String = props.getProperty("kotlinVersion") +val projectJvmTarget: String = "11" -dependencies { - implementation(kotlin("gradle-plugin-api", kotlinVersion)) +kotlin { + jvmToolchain { + (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(projectJvmTarget)) + } } -sourceSets["main"].withConvention(KotlinSourceSet::class) { kotlin.srcDirs("src") } +tasks.withType().configureEach { + kotlinOptions { + jvmTarget = projectJvmTarget + } +} kotlinDslPluginOptions { - experimentalWarning.set(false) + jvmTarget.set(projectJvmTarget) } diff --git a/buildSrc/repositories.settings.gradle.kts b/buildSrc/repositories.settings.gradle.kts new file mode 100644 index 0000000..0ce4e46 --- /dev/null +++ b/buildSrc/repositories.settings.gradle.kts @@ -0,0 +1,23 @@ +// Shared repository config, for use in both build-logic and the root project + + +@Suppress("UnstableApiUsage") // Central declaration of repositories is an incubating feature +dependencyResolutionManagement { + + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + + repositories { + mavenCentral() + gradlePluginPortal() + maven("https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev/") { + mavenContent { includeGroup("org.jetbrains.dokka") } + } + } + + pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } + } +} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000..28f89be --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1,12 @@ +rootProject.name = "buildSrc" + +apply(from = "repositories.settings.gradle.kts") + +dependencyResolutionManagement { + @Suppress("UnstableApiUsage") + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/buildSrc/src/MavenCentralMetadata.kt b/buildSrc/src/MavenCentralMetadata.kt deleted file mode 100644 index 02bbb46..0000000 --- a/buildSrc/src/MavenCentralMetadata.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.knit.build - -import org.gradle.api.* -import org.gradle.api.file.* -import org.gradle.api.publish.* -import org.gradle.api.publish.maven.* -import org.gradle.jvm.tasks.* -import org.gradle.kotlin.dsl.* - -fun PublishingExtension.mavenCentralMetadata() { - publications.withType(MavenPublication::class) { - pom { - if (!name.isPresent) { - name.set(artifactId) - } - if (!description.isPresent) { - description.set("Kotlin source code documentation management tool") - } - url.set("https://github.com/Kotlin/kotlinx-knit") - licenses { - license { - name.set("The Apache Software License, Version 2.0") - url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") - distribution.set("repo") - } - } - developers { - developer { - id.set("JetBrains") - name.set("JetBrains Team") - organization.set("JetBrains") - organizationUrl.set("https://www.jetbrains.com") - } - } - scm { - url.set("https://github.com/Kotlin/kotlinx-knit") - } - } - } -} - -fun MavenPublication.mavenCentralArtifacts(project: Project, sources: SourceDirectorySet) { - val sourcesJar by project.tasks.creating(Jar::class) { - archiveClassifier.set("sources") - from(sources) - } - val javadocJar by project.tasks.creating(Jar::class) { - archiveClassifier.set("javadoc") - // contents are deliberately left empty - } - artifact(sourcesJar) - artifact(javadocJar) -} \ No newline at end of file diff --git a/buildSrc/src/Publishing.kt b/buildSrc/src/Publishing.kt deleted file mode 100644 index 1e26787..0000000 --- a/buildSrc/src/Publishing.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.knit.build - -import org.gradle.api.* -import org.gradle.api.publish.* -import org.gradle.api.publish.maven.* -import org.gradle.plugins.signing.* -import java.net.* - - -fun PublishingExtension.mavenRepositoryPublishing(project: Project) { - repositories { - maven { - url = URI("https://oss.sonatype.org/service/local/staging/deploy/maven2/") - credentials { - username = project.getSensitiveProperty("libs.sonatype.user") - password = project.getSensitiveProperty("libs.sonatype.password") - } - } - } -} - -fun Project.signPublicationIfKeyPresent(publication: MavenPublication) { - val keyId = project.getSensitiveProperty("libs.sign.key.id") - val signingKey = project.getSensitiveProperty("libs.sign.key.private") - val signingKeyPassphrase = project.getSensitiveProperty("libs.sign.passphrase") - if (!signingKey.isNullOrBlank()) { - extensions.configure("signing") { - useInMemoryPgpKeys(keyId, signingKey, signingKeyPassphrase) - sign(publication) - } - } -} - -fun Project.getSensitiveProperty(name: String): String? { - return project.findProperty(name) as? String ?: System.getenv(name) -} diff --git a/buildSrc/src/SourceSets.kt b/buildSrc/src/SourceSets.kt deleted file mode 100644 index 65ac086..0000000 --- a/buildSrc/src/SourceSets.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.knit.build - -import org.gradle.api.* -import org.gradle.api.file.* -import org.gradle.api.tasks.* -import org.gradle.kotlin.dsl.* -import org.jetbrains.kotlin.gradle.plugin.* - -val NamedDomainObjectProvider.kotlin: SourceDirectorySet - get() = get().withConvention(KotlinSourceSet::class) { kotlin } - -val NamedDomainObjectProvider.resources: SourceDirectorySet - get() = get().resources - -val NamedDomainObjectProvider.allSource: SourceDirectorySet - get() = get().allSource - -var SourceDirectorySet.dir: String - get() = srcDirs().joinToString(",") - set(value) { setSrcDirs(value.split(",")) } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/buildsrc/config/KotlinKnitBuildSettings.kt b/buildSrc/src/main/kotlin/buildsrc/config/KotlinKnitBuildSettings.kt new file mode 100644 index 0000000..1aef6ea --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/config/KotlinKnitBuildSettings.kt @@ -0,0 +1,40 @@ +package buildsrc.config + +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import javax.inject.Inject + +/** + * Properties used to configure how the Knit project should be built. + */ +abstract class KotlinKnitBuildSettings @Inject constructor( + private val providers: ProviderFactory, +) { + val jvmTarget: Provider = gradlePropertyOrEnvVar("knit_jvmTarget").orElse("8") + + val ossrhUsername: Provider = gradlePropertyOrEnvVar("libs.sonatype.user") + val ossrhPassword: Provider = gradlePropertyOrEnvVar("libs.sonatype.password") + + val signingKeyId: Provider = gradlePropertyOrEnvVar("libs.sign.key.id") + val signingKey: Provider = gradlePropertyOrEnvVar("libs.sign.key.private") + val signingKeyPassphrase: Provider = gradlePropertyOrEnvVar("libs.sign.passphrase") + + /** + * Try to get a Gradle property (from a command line arg, a `gradle.properties` value, or a environment variable + * prefixed with `ORG_GRADLE_PROJECT_`), or an environment variable, called [name]. + */ + private fun gradlePropertyOrEnvVar(name: String): Provider = + providers.gradleProperty(name) + .orElse(providers.environmentVariable(name)) + + companion object { + const val EXTENSION_NAME = "knitBuildSettings" + + /** + * Regex for matching the release version. + * + * If a version does not match this code it should be treated as a SNAPSHOT version. + */ + val releaseVersionRegex = Regex("\\d\\+.\\d\\+.\\d+") + } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/config/distributions.kt b/buildSrc/src/main/kotlin/buildsrc/config/distributions.kt new file mode 100644 index 0000000..3cdb211 --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/config/distributions.kt @@ -0,0 +1,28 @@ +package buildsrc.config + +import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE +import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE +import org.gradle.api.model.ObjectFactory +import org.gradle.kotlin.dsl.named + +/** Mark this [Configuration] as one that will be consumed by other subprojects. */ +fun Configuration.asProvider() { + isVisible = false + isCanBeResolved = false + isCanBeConsumed = true +} + +/** Mark this [Configuration] as one that will consume (also known as 'resolving') artifacts from other subprojects */ +fun Configuration.asConsumer() { + isVisible = false + isCanBeResolved = true + isCanBeConsumed = false +} + + +fun AttributeContainer.dokkaHtmlDocsAttributes(objects: ObjectFactory) { + attribute(CATEGORY_ATTRIBUTE, objects.named("kotlinx-dokka-docs")) + attribute(USAGE_ATTRIBUTE, objects.named("html")) +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts new file mode 100644 index 0000000..396d94c --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/base.gradle.kts @@ -0,0 +1,22 @@ +package buildsrc.conventions + +import buildsrc.config.KotlinKnitBuildSettings + +plugins { + base +} + +if (project != rootProject) { + project.version = rootProject.version + project.group = rootProject.group +} + + +extensions.create(KotlinKnitBuildSettings.EXTENSION_NAME, KotlinKnitBuildSettings::class) + + +tasks.withType().configureEach { + // https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives + isPreserveFileTimestamps = false + isReproducibleFileOrder = true +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/dokka-docs-share.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/dokka-docs-share.gradle.kts new file mode 100644 index 0000000..7c066ac --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/dokka-docs-share.gradle.kts @@ -0,0 +1,20 @@ +package buildsrc.conventions + +import buildsrc.config.asConsumer +import buildsrc.config.asProvider +import buildsrc.config.dokkaHtmlDocsAttributes + +// create configurations for sharing files between subprojects in a Gradle-compatible manner. +// Subprojects that apply this plugin must manually add/consume artifacts to the necessary Gradle configurations. + +val dokkaHtmlDocs by configurations.registering { + description = "Retrieve Dokka HTML Documentation from other subprojects" + asConsumer() + attributes { dokkaHtmlDocsAttributes(objects) } +} + +val dokkaHtmlDocsElements by configurations.registering { + description = "Provide Dokka HTML Documentation to other subprojects" + asProvider() + attributes { dokkaHtmlDocsAttributes(objects) } +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/kotlin-jvm.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/kotlin-jvm.gradle.kts new file mode 100644 index 0000000..10febea --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/kotlin-jvm.gradle.kts @@ -0,0 +1,27 @@ +package buildsrc.conventions + +import buildsrc.config.KotlinKnitBuildSettings +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("buildsrc.conventions.base") + kotlin("jvm") +} + +val knitBuildSettings = extensions.getByType() + +tasks.withType().configureEach { + kotlinOptions { + jvmTarget = knitBuildSettings.jvmTarget.get() +// allWarningsAsErrors = true +// freeCompilerArgs = freeCompilerArgs + listOf("-Xsuppress-version-warnings") // suppress deprecated 1.4 + } +} + +java { + withSourcesJar() +} + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publish.gradle.kts b/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publish.gradle.kts new file mode 100644 index 0000000..0b0168e --- /dev/null +++ b/buildSrc/src/main/kotlin/buildsrc/conventions/maven-publish.gradle.kts @@ -0,0 +1,120 @@ +package buildsrc.conventions + +import buildsrc.config.KotlinKnitBuildSettings + +plugins { + `maven-publish` + signing +} + +val knitSettings = extensions.getByType() + + +val javadocJarStub by tasks.registering(Jar::class) { + group = JavaBasePlugin.DOCUMENTATION_GROUP + description = "Empty Javadoc Jar (required by Maven Central)" + archiveClassifier.set("javadoc") +} + + +val isReleaseVersion = provider { version.toString().matches(KotlinKnitBuildSettings.releaseVersionRegex) } + +val sonatypeReleaseUrl: Provider = isReleaseVersion.map { isRelease -> + if (isRelease) { + "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + } else { + "https://s01.oss.sonatype.org/content/repositories/snapshots/" + } +} + +signing { + useGpgCmd() + if (knitSettings.signingKey.isPresent) { + logger.lifecycle("[maven-publish convention] signing is enabled for ${project.path}") + useInMemoryPgpKeys( + knitSettings.signingKeyId.get(), + knitSettings.signingKey.get(), + knitSettings.signingKeyPassphrase.get(), + ) + } +} + +// Gradle hasn't updated the signing plugin to be compatible with lazy-configuration, so it needs weird workarounds: +afterEvaluate { + // Register signatures in afterEvaluate, otherwise the signing plugin creates the signing tasks + // too early, before all the publications are added. Use .all { }, not .configureEach { }, + // otherwise the signing plugin doesn't create the tasks soon enough. + + if (knitSettings.signingKey.isPresent) { + publishing.publications.all publication@{ + logger.lifecycle("[maven-publish convention] configuring signature for publication ${this@publication.name} in ${project.path}") + // closureOf is a Gradle Kotlin DSL workaround: https://github.com/gradle/gradle/issues/19903 + signing.sign(closureOf { signing.sign(this@publication) }) + } + } +} + +publishing { + repositories { + if (knitSettings.ossrhUsername.isPresent && knitSettings.ossrhPassword.isPresent) { + maven(sonatypeReleaseUrl) { + name = "SonatypeRelease" + credentials { + username = knitSettings.ossrhUsername.get() + password = knitSettings.ossrhPassword.get() + } + } + } + + // Publish to a project-local Maven directory, for verification. To test, run: + // ./gradlew publishAllPublicationsToMavenProjectLocalRepository + // and check $rootDir/build/maven-project-local + maven(rootProject.layout.buildDirectory.dir("maven-project-local")) { + name = "MavenProjectLocal" + } + } + + publications.withType().configureEach { + + artifact(javadocJarStub) + + pom { + description.convention("Kotlin source code documentation management tool") + url.set("https://github.com/Kotlin/kotlinx-knit") + licenses { + license { + name.set("The Apache Software License, Version 2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") + distribution.set("repo") + } + } + developers { + developer { + id.set("JetBrains") + name.set("JetBrains Team") + organization.set("JetBrains") + organizationUrl.set("https://www.jetbrains.com") + } + } + scm { + url.set("https://github.com/Kotlin/kotlinx-knit") + } + } + } +} + +tasks.withType().configureEach { + // Gradle warns about some signing tasks using publishing task outputs without explicit dependencies. + // Here's a quick fix. + dependsOn(tasks.withType()) + mustRunAfter(tasks.withType()) + + // use a val for the GAV to avoid Gradle Configuration Cache issues + val publicationGAV = publication?.run { "$group:$artifactId:$version" } + + doLast { + if (publicationGAV != null) { + logger.lifecycle("[task: ${path}] $publicationGAV") + } + } +} diff --git a/gradle.properties b/gradle.properties index 1cc9512..75889ef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,17 @@ -# # Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. # - -version=0.4.0-SNAPSHOT -group=org.jetbrains.kotlinx - -kotlinVersion=1.6.10 -dokkaVersion=1.6.10 -freemarkerVersion=2.3.29 -pluginPublishVersion=0.15.0 +org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx2g +# +knit_jvmTarget=11 +# +# https://docs.gradle.org/current/userguide/build_cache.html +org.gradle.parallel=true +org.gradle.caching=true +# +# https://docs.gradle.org/current/userguide/configuration_cache.html +# can't enable config-cache - Dokka is totally incompatible https://github.com/Kotlin/dokka/issues/2231 +#org.gradle.unsafe.configuration-cache=true +#org.gradle.unsafe.configuration-cache-problems=warn +# +# cache accessors - defaults to 'true' in Gradle 8.0 https://github.com/gradle/gradle/issues/20416 +org.gradle.kotlin.dsl.precompiled.accessors.strict=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..8d41379 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,64 @@ +[versions] + +kotlin = "1.7.21" +kotlinx-serialization = "1.4.1" +dokka = "1.7.20" +jackson = "2.11.1" +slf4j = "1.7.36" +freemarker = "2.3.29" + +gradlePluginPublish = "1.1.0" + + +[libraries] + +## Kotlin stdlib ## +kotlin-bom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" } + +## Jackson ## +jackson-bom = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "jackson" } +jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin" } +jackson-xml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-xml" } + +### KotlinX Serialization ## +#kotlinxSerialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-serialization-bom", version.ref = "kotlinx-serialization" } +#kotlinxSerialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } +#kotlinxSerialization-cbor = { module = "org.jetbrains.kotlinx:kotlinx-serialization-cbor" } +#kotlinxSerialization-hocon = { module = "org.jetbrains.kotlinx:kotlinx-serialization-hocon" } +#kotlinxSerialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } +#kotlinxSerialization-properties = { module = "org.jetbrains.kotlinx:kotlinx-serialization-properties" } +#kotlinxSerialization-protobuf = { module = "org.jetbrains.kotlinx:kotlinx-serialization-protobuf" } +#kotlinxSerialization-jsonOkio = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-okio" } + + +## Freemarker ## +freemarker = { module = "org.freemarker:freemarker", version.ref = "freemarker" } + +## Dokka ## +dokka-core = { module = "org.jetbrains.dokka:dokka-core", version.ref = "dokka" } +dokka-base = { module = "org.jetbrains.dokka:dokka-base", version.ref = "dokka" } +dokka-templatingPlugin = { module = "org.jetbrains.dokka:templating-plugin", version.ref = "dokka" } + + +## Logging ## +slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } + + + +### Gradle plugins ### +# Maven coordinates of Gradle plugins. Used in ./build-logic/build.gradle.kts. +gradlePlugin-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +gradlePlugin-kotlinSerialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" } + +gradlePlugin-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" } + +gradlePlugin-gradlePluginPublish = { module = "com.gradle.publish:plugin-publish-plugin", version.ref = "gradlePluginPublish" } + + +[bundles] + + +[plugins] + +# define plugins in ./build-logic/build.gradle.kts to avoid error: +# The Kotlin Gradle plugin was loaded multiple times in different subprojects, which is not supported and may break the build. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c..249e583 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..ae04661 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..a69d9cb 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,101 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd3..f127cfd 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/kotlinx-knit-core/build.gradle.kts b/kotlinx-knit-core/build.gradle.kts new file mode 100644 index 0000000..463e486 --- /dev/null +++ b/kotlinx-knit-core/build.gradle.kts @@ -0,0 +1,36 @@ +plugins { + buildsrc.conventions.`kotlin-jvm` + buildsrc.conventions.`maven-publish` + buildsrc.conventions.`dokka-docs-share` +} + +dependencies { + implementation(projects.kotlinxKnitTest) + implementation(projects.kotlinxKnitDokka) + + implementation(libs.slf4j.api) + + implementation(libs.freemarker) + implementation(libs.dokka.core) + + implementation(platform(libs.jackson.bom)) + implementation(libs.jackson.kotlin) + implementation(libs.jackson.xml) + + testImplementation(kotlin("test-junit5")) + + dokkaHtmlDocs(projects.kotlinxKnitTest) +} + +publishing { + publications { + register("dokkaPlugin") { + artifactId = "knit-core" + from(components["java"]) + } + } +} + +tasks.test { + dependsOn(configurations.dokkaHtmlDocs) +} diff --git a/src/Knit.kt b/kotlinx-knit-core/src/main/kotlin/Knit.kt similarity index 96% rename from src/Knit.kt rename to kotlinx-knit-core/src/main/kotlin/Knit.kt index 808fbcd..d554d87 100644 --- a/src/Knit.kt +++ b/kotlinx-knit-core/src/main/kotlin/Knit.kt @@ -4,11 +4,12 @@ package kotlinx.knit +import kotlinx.knit.internal.div +import kotlinx.knit.internal.firstLineSeparator +import kotlinx.knit.internal.withLineNumberReader import kotlinx.knit.test.* import java.io.* import java.util.* -import kotlin.collections.ArrayList -import kotlin.collections.HashMap import kotlin.properties.* import kotlin.system.* @@ -126,7 +127,7 @@ class KnitIncludeEnv( fun loadMainInclude(file: File, props: KnitProps, knitName: String): List = props.loadTemplateLines(KNIT_INCLUDE_PROP, KnitIncludeEnv(file, props, knitName)) + - "" // empty line after the main include + "" // empty line after the main include // Reference to knitted example's full package (pkg.name) class KnitRef(val props: KnitProps, val name: String) @@ -185,7 +186,7 @@ fun KnitContext.knit(inputFile: File): Boolean { } knitAutonumberIndex[key] = index + 1 } - require(files.add(file)) { "Duplicate file: $file"} + require(files.add(file)) { "Duplicate file: $file" } log.info("Knitting $file ...") // -- PREFIX -- val outLines = prefixLines.toMutableList() @@ -216,6 +217,7 @@ fun KnitContext.knit(inputFile: File): Boolean { writeLinesIfNeeded(file, outLines) lastKnit = KnitRef(props, knitName) } + // Processes INCLUDE and PREFIX directives with pattern fun saveInclude(directive: Directive, type: IncludeType) { require(directive.param.isNotEmpty()) @@ -232,13 +234,16 @@ fun KnitContext.knit(inputFile: File): Boolean { } // Match directives when (directive?.name) { - null, END_DIRECTIVE -> { /* do nothing, END works like NOP, too */ } + null, END_DIRECTIVE -> { /* do nothing, END works like NOP, too */ + } + TOC_DIRECTIVE -> { requireSingleLine(directive) require(directive.param.isEmpty()) { "$TOC_DIRECTIVE directive must not have parameters" } require(inputTextPart == InputTextPart.PRE_TOC) { "Only one TOC directive is supported" } inputTextPart = InputTextPart.TOC } + TOC_REF_DIRECTIVE -> { requireSingleLine(directive) require(directive.param.isNotEmpty()) { "$TOC_REF_DIRECTIVE directive must include reference file path" } @@ -255,6 +260,7 @@ fun KnitContext.knit(inputFile: File): Boolean { if (!replaceUntilNextDirective(lines)) error("Unexpected end of file after $TOC_REF_DIRECTIVE") } } + INCLUDE_DIRECTIVE -> { if (directive.param.isEmpty()) { require(!directive.singleLine) { "$INCLUDE_DIRECTIVE directive without parameters must not be single line" } @@ -264,6 +270,7 @@ fun KnitContext.knit(inputFile: File): Boolean { } continue@mainLoop } + PREFIX_DIRECTIVE -> { if (directive.param.isEmpty()) { if (directive.singleLine) { @@ -277,6 +284,7 @@ fun KnitContext.knit(inputFile: File): Boolean { } continue@mainLoop } + SUFFIX_DIRECTIVE -> { if (directive.param.isEmpty()) { if (directive.singleLine) { @@ -290,12 +298,14 @@ fun KnitContext.knit(inputFile: File): Boolean { } continue@mainLoop } + CLEAR_DIRECTIVE -> { requireSingleLine(directive) require(directive.param.isEmpty()) { "$CLEAR_DIRECTIVE directive must not have parameters" } codeLines.clear() continue@mainLoop } + KNIT_DIRECTIVE -> { requireSingleLine(directive) require(knit != null) { "'$KNIT_DIR_PROP' property must be configured to use $KNIT_DIRECTIVE directive" } @@ -307,19 +317,21 @@ fun KnitContext.knit(inputFile: File): Boolean { numberMatch = match.groups[1]!! + directive.paramOffset ) } + TEST_NAME_DIRECTIVE -> { requireSingleLine(directive) require(directive.param.isNotEmpty()) { "$TEST_NAME_DIRECTIVE directive must include name parameter" } flushTestOut(inputFile, props, testName, testCases) testName = directive.param } + TEST_DIRECTIVE -> { require(lastKnit != null) { "$TEST_DIRECTIVE must be preceded by knitted file" } require(testName != null) { "Neither $TEST_NAME_DIRECTIVE directive nor '$TEST_NAME_PROP' property was specified" } val param = directive.param if (testLines.isEmpty()) { if (directive.singleLine) { - require(param.isNotEmpty()) { "$TEST_DIRECTIVE must be preceded by $testStartLang block or contain test parameter"} + require(param.isNotEmpty()) { "$TEST_DIRECTIVE must be preceded by $testStartLang block or contain test parameter" } } else readUntilToDirectiveEnd(linePrefix, testLines) } else { @@ -328,12 +340,17 @@ fun KnitContext.knit(inputFile: File): Boolean { testCases += makeTest(lastKnit!!, testLines.toList(), param) testLines.clear() } + MODULE_DIRECTIVE -> { requireSingleLine(directive) val isRoot = directive.param.startsWith('/') moduleName = if (isRoot) directive.param.substring(1) else directive.param - docsRoot = findMultiModuleRoot() ?: findModuleRoot(isRoot, moduleName) + "/" + moduleDocs + "/" + moduleName + docsRoot = findMultiModuleRoot() ?: (findModuleRoot( + isRoot, + moduleName + ) + "/" + moduleDocs + "/" + moduleName) } + INDEX_DIRECTIVE -> { requireSingleLine(directive) require(siteRoot != null) { "Missing 'siteRoot' in knit configuration, cannot do $INDEX_DIRECTIVE" } @@ -363,6 +380,7 @@ fun KnitContext.knit(inputFile: File): Boolean { } if (!replaceUntilNextDirective(result)) error("Unexpected end of file after $INDEX_DIRECTIVE") } + else -> { error("Unrecognized knit directive '${directive.name}' on a line starting with '$DIRECTIVE_START'") } @@ -453,7 +471,7 @@ private fun String.capitalizeAfter(char: Char): String = buildString { var cap = false for (c in this@capitalizeAfter) { cap = if (c == char) true else { - append(if (cap) c.toUpperCase() else c) + append(if (cap) c.uppercaseChar() else c) false } } @@ -486,7 +504,12 @@ class TestCase( val knit = props.getMap("knit", "name" to knitName) } -private fun KnitContext.flushTestOut(file: File, props: KnitProps, testName: String?, testCases: MutableList) { +private fun KnitContext.flushTestOut( + file: File, + props: KnitProps, + testName: String?, + testCases: MutableList +) { if (testCases.isEmpty()) return if (testName == null) return val lines = props.loadTemplateLines(TEST_TEMPLATE_PROP, TestTemplateEnv(file, props, testName, testCases)) @@ -522,6 +545,7 @@ private fun InputTextReader.readUntilToDirectiveEnd(linePrefix: String, list: Mu putBackLine = linePrefix + DIRECTIVE_START + line.substring(DIRECTIVE_NEXT.length) true } + else -> false } } @@ -542,7 +566,7 @@ private const val skippedTocSymbols = "\\,`*{}[]()/#+.!:" fun makeSectionRef(name: String): String = name .replace(' ', '-') .replace(("[" + Regex.escape(skippedTocSymbols) + "]").toRegex(), "") - .toLowerCase() + .lowercase() enum class IncludeType { INCLUDE, PREFIX, SUFFIX } @@ -612,11 +636,12 @@ class InputTextReader(val inputFileType: InputFileType, r: Reader) : LineNumberR var skip = false var putBackLine: String? = null - val outText: MutableList get() = when (inputTextPart) { - InputTextPart.PRE_TOC -> preTocText - InputTextPart.POST_TOC -> postTocText - else -> throw IllegalStateException("Wrong state: $inputTextPart") - } + val outText: MutableList + get() = when (inputTextPart) { + InputTextPart.PRE_TOC -> preTocText + InputTextPart.POST_TOC -> postTocText + else -> throw IllegalStateException("Wrong state: $inputTextPart") + } override fun readLine(): String? { putBackLine?.let { @@ -652,7 +677,11 @@ class InputTextReader(val inputFileType: InputFileType, r: Reader) : LineNumberR } } -fun KnitContext.withInputTextReader(file: File, type: InputFileType, block: InputTextReader.() -> Unit): InputTextReader? = +fun KnitContext.withInputTextReader( + file: File, + type: InputFileType, + block: InputTextReader.() -> Unit +): InputTextReader? = withLineNumberReader(file, { r -> InputTextReader(type, r) }, block) fun KnitContext.writeLinesIfNeeded(file: File, outLines: List) { @@ -699,7 +728,7 @@ private fun KnitContext.writeLines(file: File, lines: List) { } fun KnitContext.findMultiModuleRoot(): String? = - dokkaMultiModuleRoot.takeIf { rootDir.resolve(it).exists() } + dokkaMultiModuleRoot.takeIf { rootDir.resolve(it).exists() } fun KnitContext.findModuleRoot(isRoot: Boolean, name: String): String = moduleRoots diff --git a/src/KnitApiParser.kt b/kotlinx-knit-core/src/main/kotlin/KnitApiParser.kt similarity index 97% rename from src/KnitApiParser.kt rename to kotlinx-knit-core/src/main/kotlin/KnitApiParser.kt index 02e1fed..58ac4fe 100644 --- a/src/KnitApiParser.kt +++ b/kotlinx-knit-core/src/main/kotlin/KnitApiParser.kt @@ -6,9 +6,10 @@ package kotlinx.knit import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue -import kotlinx.knit.pathsaver.DocumentableType -import kotlinx.knit.pathsaver.LINK_INDEX_FILE -import kotlinx.knit.pathsaver.LinkIndexEntry +import kotlinx.knit.dokka.DocumentableType +import kotlinx.knit.dokka.LINK_INDEX_FILE +import kotlinx.knit.dokka.LinkIndexEntry +import kotlinx.knit.internal.div import org.jetbrains.dokka.links.Nullable import org.jetbrains.dokka.links.TypeConstructor import org.jetbrains.dokka.links.TypeReference diff --git a/src/KnitContext.kt b/kotlinx-knit-core/src/main/kotlin/KnitContext.kt similarity index 100% rename from src/KnitContext.kt rename to kotlinx-knit-core/src/main/kotlin/KnitContext.kt diff --git a/src/KnitLog.kt b/kotlinx-knit-core/src/main/kotlin/KnitLog.kt similarity index 94% rename from src/KnitLog.kt rename to kotlinx-knit-core/src/main/kotlin/KnitLog.kt index 8721477..7dcb2db 100644 --- a/src/KnitLog.kt +++ b/kotlinx-knit-core/src/main/kotlin/KnitLog.kt @@ -43,7 +43,7 @@ class ConsoleLog : KnitLog() { } class LoggerLog : KnitLog() { - private val logger: Logger by lazy { LoggerFactory.getLogger("knit") } + private val logger: Logger = LoggerFactory.getLogger("knit") override fun debug(s: String) { logger.debug(s) @@ -62,4 +62,4 @@ class LoggerLog : KnitLog() { logger.error(s) hasWarningOrError = true } -} \ No newline at end of file +} diff --git a/src/KnitProps.kt b/kotlinx-knit-core/src/main/kotlin/KnitProps.kt similarity index 100% rename from src/KnitProps.kt rename to kotlinx-knit-core/src/main/kotlin/KnitProps.kt diff --git a/src/KnitUtil.kt b/kotlinx-knit-core/src/main/kotlin/internal/KnitUtil.kt similarity index 75% rename from src/KnitUtil.kt rename to kotlinx-knit-core/src/main/kotlin/internal/KnitUtil.kt index 9918d87..93b1c9a 100644 --- a/src/KnitUtil.kt +++ b/kotlinx-knit-core/src/main/kotlin/internal/KnitUtil.kt @@ -2,11 +2,12 @@ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ -package kotlinx.knit +package kotlinx.knit.internal +import kotlinx.knit.KnitContext import java.io.* -fun KnitContext.withLineNumberReader(file: File, factory: (Reader) -> T, block: T.() -> Unit): T? { +internal fun KnitContext.withLineNumberReader(file: File, factory: (Reader) -> T, block: T.() -> Unit): T? { val reader = factory(file.reader()) reader.use { try { @@ -19,7 +20,7 @@ fun KnitContext.withLineNumberReader(file: File, factory: return reader } -operator fun File.div(path: String): File = File(this, path.replace("/", File.separator)) +internal operator fun File.div(path: String): File = File(this, path.replace("/", File.separator)) internal fun Reader.firstLineSeparator(): String? { val n = '\n'.toInt() diff --git a/resources/knit.code.include b/kotlinx-knit-core/src/main/resources/knit.code.include similarity index 100% rename from resources/knit.code.include rename to kotlinx-knit-core/src/main/resources/knit.code.include diff --git a/resources/knit.properties b/kotlinx-knit-core/src/main/resources/knit.properties similarity index 100% rename from resources/knit.properties rename to kotlinx-knit-core/src/main/resources/knit.properties diff --git a/resources/knit.test.template b/kotlinx-knit-core/src/main/resources/knit.test.template similarity index 100% rename from resources/knit.test.template rename to kotlinx-knit-core/src/main/resources/knit.test.template diff --git a/test/CaptureVerifyTest.kt b/kotlinx-knit-core/src/test/kotlin/CaptureVerifyTest.kt similarity index 97% rename from test/CaptureVerifyTest.kt rename to kotlinx-knit-core/src/test/kotlin/CaptureVerifyTest.kt index 00a1985..bdff9fb 100644 --- a/test/CaptureVerifyTest.kt +++ b/kotlinx-knit-core/src/test/kotlin/CaptureVerifyTest.kt @@ -4,8 +4,8 @@ package kotlinx.knit -import org.junit.Test import kotlinx.knit.test.* +import kotlin.test.* class CaptureVerifyTest { @Test @@ -41,4 +41,3 @@ class CaptureVerifyTest { check(1 == 2) { "The check has failed" } } } - diff --git a/test/KnitUtilTest.kt b/kotlinx-knit-core/src/test/kotlin/KnitUtilTest.kt similarity index 96% rename from test/KnitUtilTest.kt rename to kotlinx-knit-core/src/test/kotlin/KnitUtilTest.kt index 5d3e969..2b49359 100644 --- a/test/KnitUtilTest.kt +++ b/kotlinx-knit-core/src/test/kotlin/KnitUtilTest.kt @@ -1,6 +1,6 @@ package kotlinx.knit -import org.junit.Test +import kotlin.test.* import kotlin.test.assertEquals class KnitUtilTest { diff --git a/test/TestDataGen.kt b/kotlinx-knit-core/src/test/kotlin/TestDataGen.kt similarity index 88% rename from test/TestDataGen.kt rename to kotlinx-knit-core/src/test/kotlin/TestDataGen.kt index 42e9994..e302751 100644 --- a/test/TestDataGen.kt +++ b/kotlinx-knit-core/src/test/kotlin/TestDataGen.kt @@ -6,10 +6,24 @@ package kotlinx.knit import java.io.* import java.nio.file.* +import kotlin.io.path.absolute +import kotlin.io.path.absolutePathString import kotlin.streams.* import kotlin.test.* -private val TEST_DATA_DIR = Paths.get("testdata") + +//private val TEST_DATA_DIR = System.getProperty("TEST_DATA_DIR").let { +// println("TEST_DATA_DIR $it") +// Paths.get(it) +//} + +val TEST_DATA_DIR = Paths.get(object {}::class.java.getResource("testdata")!!.toURI()) +//= run { +// println("current path ${Paths.get(".").absolutePathString()}") +// val x = Paths.get("testdata").absolute() +// println("test data $x") +// x +//} private val TEST_KT = Paths.get("test", "TestDataTest.kt") private const val PROPERTIES_SUFFIX = ".properties" diff --git a/test/TestDataTest.kt b/kotlinx-knit-core/src/test/kotlin/TestDataTest.kt similarity index 99% rename from test/TestDataTest.kt rename to kotlinx-knit-core/src/test/kotlin/TestDataTest.kt index ba1f321..e15a4fa 100644 --- a/test/TestDataTest.kt +++ b/kotlinx-knit-core/src/test/kotlin/TestDataTest.kt @@ -26,7 +26,7 @@ class TestDataTest { "DokkaBasic", "testdata/dokka-basic.in.md", "testdata/dokka-basic.out.md", - null + "testdata/dokka-basic.properties" ) } @@ -48,7 +48,7 @@ class TestDataTest { "DokkaRefs", "testdata/dokka-refs.in.md", "testdata/dokka-refs.out.md", - null + "testdata/dokka-refs.properties" ) } diff --git a/test/TestDataUtil.kt b/kotlinx-knit-core/src/test/kotlin/TestDataUtil.kt similarity index 81% rename from test/TestDataUtil.kt rename to kotlinx-knit-core/src/test/kotlin/TestDataUtil.kt index b013618..23b0c7b 100644 --- a/test/TestDataUtil.kt +++ b/kotlinx-knit-core/src/test/kotlin/TestDataUtil.kt @@ -30,21 +30,23 @@ fun verifyTestData( deleteDirectory(dir) Files.createDirectories(dir) // copy files - val inPath = Paths.get(inFile) + val inPath = Resources.getFile(inFile) val targetPath = dir.resolve(inPath.fileName) Files.copy(inPath, targetPath) - if (propFile != null) Files.copy(Paths.get(propFile), dir.resolve("knit.properties")) + + if (propFile != null) Files.copy(Resources.getFile(propFile), dir.resolve("knit.properties")) + refs.filterIsInstance().forEach { ref -> - val path = Paths.get(ref.path) + val path = Resources.getFile(ref.path) Files.copy(path, dir.resolve(path.fileName)) } // run knit val context = createDefaultContext(listOf(targetPath.toFile()), dir.toFile()) assertTrue(context.process(), "Knit failed, see log") // verify resulting files - assertSameFile(Paths.get(outFile), targetPath) + assertSameFile(Resources.getFile(outFile), targetPath) refs.filterIsInstance().forEach { ref -> - val expected = Paths.get(ref.path) + val expected = Resources.getFile(ref.path) val actual = targetPath.parent.resolve(inPath.parent.relativize(expected)) assertSameFile(expected, actual) } @@ -66,3 +68,10 @@ private fun deleteDirectory(dir: Path) { it.asSequence().sortedDescending().forEach { Files.delete(it) } } } + +private object Resources { + fun getFile(path: String): Path { + return Paths.get(Resources::class.java.classLoader.getResource(path)!!.toURI()) + } + +} diff --git a/testdata/custom-prop.copy.knit.template b/kotlinx-knit-core/src/test/resources/testdata/custom-prop.copy.knit.template similarity index 100% rename from testdata/custom-prop.copy.knit.template rename to kotlinx-knit-core/src/test/resources/testdata/custom-prop.copy.knit.template diff --git a/testdata/custom-prop.copy.test.template b/kotlinx-knit-core/src/test/resources/testdata/custom-prop.copy.test.template similarity index 100% rename from testdata/custom-prop.copy.test.template rename to kotlinx-knit-core/src/test/resources/testdata/custom-prop.copy.test.template diff --git a/testdata/custom-prop.in.md b/kotlinx-knit-core/src/test/resources/testdata/custom-prop.in.md similarity index 100% rename from testdata/custom-prop.in.md rename to kotlinx-knit-core/src/test/resources/testdata/custom-prop.in.md diff --git a/testdata/custom-prop.properties b/kotlinx-knit-core/src/test/resources/testdata/custom-prop.properties similarity index 100% rename from testdata/custom-prop.properties rename to kotlinx-knit-core/src/test/resources/testdata/custom-prop.properties diff --git a/testdata/custom-prop/example-custom-01.kt b/kotlinx-knit-core/src/test/resources/testdata/custom-prop/example-custom-01.kt similarity index 100% rename from testdata/custom-prop/example-custom-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/custom-prop/example-custom-01.kt diff --git a/testdata/custom-prop/test/CustomPropTest.kt b/kotlinx-knit-core/src/test/resources/testdata/custom-prop/test/CustomPropTest.kt similarity index 100% rename from testdata/custom-prop/test/CustomPropTest.kt rename to kotlinx-knit-core/src/test/resources/testdata/custom-prop/test/CustomPropTest.kt diff --git a/testdata/dokka-html.in.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-basic.in.md similarity index 100% rename from testdata/dokka-html.in.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-basic.in.md diff --git a/testdata/dokka-root.out.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-basic.out.md similarity index 100% rename from testdata/dokka-root.out.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-basic.out.md diff --git a/kotlinx-knit-core/src/test/resources/testdata/dokka-basic.properties b/kotlinx-knit-core/src/test/resources/testdata/dokka-basic.properties new file mode 100644 index 0000000..10f401e --- /dev/null +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-basic.properties @@ -0,0 +1 @@ +module.roots=../kotlinx-knit-test diff --git a/testdata/dokka-root.in.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-html.in.md similarity index 100% rename from testdata/dokka-root.in.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-html.in.md diff --git a/testdata/dokka-html.out.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-html.out.md similarity index 100% rename from testdata/dokka-html.out.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-html.out.md diff --git a/testdata/dokka-html.properties b/kotlinx-knit-core/src/test/resources/testdata/dokka-html.properties similarity index 64% rename from testdata/dokka-html.properties rename to kotlinx-knit-core/src/test/resources/testdata/dokka-html.properties index 1a180b3..2f3ba07 100644 --- a/testdata/dokka-html.properties +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-html.properties @@ -1,3 +1,3 @@ site.root=https://example.com/html -module.roots=kotlinx-knit-test +module.roots=../kotlinx-knit-test module.docs=build/dokkaHtml diff --git a/testdata/dokka-refs.in.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.in.md similarity index 95% rename from testdata/dokka-refs.in.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-refs.in.md index 4d1c8ba..9e7cf3a 100644 --- a/testdata/dokka-refs.in.md +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.in.md @@ -13,6 +13,6 @@ For classes: * [ComputedLinesDiff] is a simple reference. * [kotlinx.knit.test.ComputedLinesDiff] is a fully qualified reference. - + diff --git a/testdata/dokka-refs.out.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.out.md similarity index 98% rename from testdata/dokka-refs.out.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-refs.out.md index 09484c7..b6f6ce0 100644 --- a/testdata/dokka-refs.out.md +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.out.md @@ -13,7 +13,7 @@ For classes: * [ComputedLinesDiff] is a simple reference. * [kotlinx.knit.test.ComputedLinesDiff] is a fully qualified reference. - + [captureOutput]: https://example.com/kotlinx-knit-test/kotlinx.knit.test/capture-output.html diff --git a/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.properties b/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.properties new file mode 100644 index 0000000..10f401e --- /dev/null +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-refs.properties @@ -0,0 +1 @@ +module.roots=../kotlinx-knit-test diff --git a/testdata/dokka-basic.in.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-root.in.md similarity index 72% rename from testdata/dokka-basic.in.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-root.in.md index 0ae3998..2d8c23a 100644 --- a/testdata/dokka-basic.in.md +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-root.in.md @@ -1,5 +1,5 @@ Here is a link to [captureOutput] function. - + diff --git a/testdata/dokka-basic.out.md b/kotlinx-knit-core/src/test/resources/testdata/dokka-root.out.md similarity index 83% rename from testdata/dokka-basic.out.md rename to kotlinx-knit-core/src/test/resources/testdata/dokka-root.out.md index 1b7b350..45b7431 100644 --- a/testdata/dokka-basic.out.md +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-root.out.md @@ -1,6 +1,6 @@ Here is a link to [captureOutput] function. - + [captureOutput]: https://example.com/kotlinx-knit-test/kotlinx.knit.test/capture-output.html diff --git a/kotlinx-knit-core/src/test/resources/testdata/dokka-root.properties b/kotlinx-knit-core/src/test/resources/testdata/dokka-root.properties new file mode 100644 index 0000000..10f401e --- /dev/null +++ b/kotlinx-knit-core/src/test/resources/testdata/dokka-root.properties @@ -0,0 +1 @@ +module.roots=../kotlinx-knit-test diff --git a/testdata/example-basic.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-basic.in.md similarity index 100% rename from testdata/example-basic.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-basic.in.md diff --git a/testdata/example-basic.properties b/kotlinx-knit-core/src/test/resources/testdata/example-basic.properties similarity index 100% rename from testdata/example-basic.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-basic.properties diff --git a/testdata/example-basic/example-basic-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-basic/example-basic-01.kt similarity index 100% rename from testdata/example-basic/example-basic-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-basic/example-basic-01.kt diff --git a/testdata/example-include.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-include.in.md similarity index 100% rename from testdata/example-include.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-include.in.md diff --git a/testdata/example-include.properties b/kotlinx-knit-core/src/test/resources/testdata/example-include.properties similarity index 100% rename from testdata/example-include.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-include.properties diff --git a/testdata/example-include/example-include-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-include/example-include-01.kt similarity index 100% rename from testdata/example-include/example-include-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-include/example-include-01.kt diff --git a/testdata/example-kdoc.in.kt b/kotlinx-knit-core/src/test/resources/testdata/example-kdoc.in.kt similarity index 100% rename from testdata/example-kdoc.in.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-kdoc.in.kt diff --git a/testdata/example-kdoc.out.kt b/kotlinx-knit-core/src/test/resources/testdata/example-kdoc.out.kt similarity index 100% rename from testdata/example-kdoc.out.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-kdoc.out.kt diff --git a/testdata/example-kdoc.properties b/kotlinx-knit-core/src/test/resources/testdata/example-kdoc.properties similarity index 100% rename from testdata/example-kdoc.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-kdoc.properties diff --git a/testdata/example-kdoc/example-kdoc-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-kdoc/example-kdoc-01.kt similarity index 100% rename from testdata/example-kdoc/example-kdoc-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-kdoc/example-kdoc-01.kt diff --git a/testdata/example-knit.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-knit.in.md similarity index 100% rename from testdata/example-knit.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-knit.in.md diff --git a/testdata/example-knit.out.md b/kotlinx-knit-core/src/test/resources/testdata/example-knit.out.md similarity index 100% rename from testdata/example-knit.out.md rename to kotlinx-knit-core/src/test/resources/testdata/example-knit.out.md diff --git a/testdata/example-knit.properties b/kotlinx-knit-core/src/test/resources/testdata/example-knit.properties similarity index 100% rename from testdata/example-knit.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-knit.properties diff --git a/testdata/example-knit/example-knit-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-knit/example-knit-01.kt similarity index 100% rename from testdata/example-knit/example-knit-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-knit/example-knit-01.kt diff --git a/testdata/example-merge.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-merge.in.md similarity index 100% rename from testdata/example-merge.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-merge.in.md diff --git a/testdata/example-merge.properties b/kotlinx-knit-core/src/test/resources/testdata/example-merge.properties similarity index 100% rename from testdata/example-merge.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-merge.properties diff --git a/testdata/example-merge/example-merge-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-merge/example-merge-01.kt similarity index 100% rename from testdata/example-merge/example-merge-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-merge/example-merge-01.kt diff --git a/testdata/example-patternmatch.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-patternmatch.in.md similarity index 100% rename from testdata/example-patternmatch.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-patternmatch.in.md diff --git a/testdata/example-patternmatch.properties b/kotlinx-knit-core/src/test/resources/testdata/example-patternmatch.properties similarity index 100% rename from testdata/example-patternmatch.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-patternmatch.properties diff --git a/testdata/example-patternmatch/example-patternmatch-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-patternmatch/example-patternmatch-01.kt similarity index 100% rename from testdata/example-patternmatch/example-patternmatch-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-patternmatch/example-patternmatch-01.kt diff --git a/testdata/example-patternmatch/example-patternmatch-02.kt b/kotlinx-knit-core/src/test/resources/testdata/example-patternmatch/example-patternmatch-02.kt similarity index 100% rename from testdata/example-patternmatch/example-patternmatch-02.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-patternmatch/example-patternmatch-02.kt diff --git a/testdata/example-patternmatch/example-patternmatch-03.kt b/kotlinx-knit-core/src/test/resources/testdata/example-patternmatch/example-patternmatch-03.kt similarity index 100% rename from testdata/example-patternmatch/example-patternmatch-03.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-patternmatch/example-patternmatch-03.kt diff --git a/testdata/example-prefix-comment.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-prefix-comment.in.md similarity index 100% rename from testdata/example-prefix-comment.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-prefix-comment.in.md diff --git a/testdata/example-prefix-comment.properties b/kotlinx-knit-core/src/test/resources/testdata/example-prefix-comment.properties similarity index 100% rename from testdata/example-prefix-comment.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-prefix-comment.properties diff --git a/testdata/example-prefix-comment/example-prefix-comment-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-prefix-comment/example-prefix-comment-01.kt similarity index 100% rename from testdata/example-prefix-comment/example-prefix-comment-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-prefix-comment/example-prefix-comment-01.kt diff --git a/testdata/example-prefix.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-prefix.in.md similarity index 100% rename from testdata/example-prefix.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-prefix.in.md diff --git a/testdata/example-prefix.properties b/kotlinx-knit-core/src/test/resources/testdata/example-prefix.properties similarity index 100% rename from testdata/example-prefix.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-prefix.properties diff --git a/testdata/example-prefix/example-prefix-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-prefix/example-prefix-01.kt similarity index 100% rename from testdata/example-prefix/example-prefix-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-prefix/example-prefix-01.kt diff --git a/testdata/example-print.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-print.in.md similarity index 100% rename from testdata/example-print.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-print.in.md diff --git a/testdata/example-print.properties b/kotlinx-knit-core/src/test/resources/testdata/example-print.properties similarity index 100% rename from testdata/example-print.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-print.properties diff --git a/testdata/example-print/example-print-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-print/example-print-01.kt similarity index 100% rename from testdata/example-print/example-print-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-print/example-print-01.kt diff --git a/testdata/example-renumber.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-renumber.in.md similarity index 100% rename from testdata/example-renumber.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-renumber.in.md diff --git a/testdata/example-renumber.out.md b/kotlinx-knit-core/src/test/resources/testdata/example-renumber.out.md similarity index 100% rename from testdata/example-renumber.out.md rename to kotlinx-knit-core/src/test/resources/testdata/example-renumber.out.md diff --git a/testdata/example-renumber.properties b/kotlinx-knit-core/src/test/resources/testdata/example-renumber.properties similarity index 100% rename from testdata/example-renumber.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-renumber.properties diff --git a/testdata/example-renumber/example-renumber-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-renumber/example-renumber-01.kt similarity index 100% rename from testdata/example-renumber/example-renumber-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-renumber/example-renumber-01.kt diff --git a/testdata/example-renumber/example-renumber-02.kt b/kotlinx-knit-core/src/test/resources/testdata/example-renumber/example-renumber-02.kt similarity index 100% rename from testdata/example-renumber/example-renumber-02.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-renumber/example-renumber-02.kt diff --git a/testdata/example-suffix.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-suffix.in.md similarity index 100% rename from testdata/example-suffix.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-suffix.in.md diff --git a/testdata/example-suffix.properties b/kotlinx-knit-core/src/test/resources/testdata/example-suffix.properties similarity index 100% rename from testdata/example-suffix.properties rename to kotlinx-knit-core/src/test/resources/testdata/example-suffix.properties diff --git a/testdata/example-suffix/example-suffix-01.kt b/kotlinx-knit-core/src/test/resources/testdata/example-suffix/example-suffix-01.kt similarity index 100% rename from testdata/example-suffix/example-suffix-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/example-suffix/example-suffix-01.kt diff --git a/testdata/example-toc.in.md b/kotlinx-knit-core/src/test/resources/testdata/example-toc.in.md similarity index 100% rename from testdata/example-toc.in.md rename to kotlinx-knit-core/src/test/resources/testdata/example-toc.in.md diff --git a/testdata/example-toc.out.md b/kotlinx-knit-core/src/test/resources/testdata/example-toc.out.md similarity index 100% rename from testdata/example-toc.out.md rename to kotlinx-knit-core/src/test/resources/testdata/example-toc.out.md diff --git a/testdata/include-prop.copy.template b/kotlinx-knit-core/src/test/resources/testdata/include-prop.copy.template similarity index 100% rename from testdata/include-prop.copy.template rename to kotlinx-knit-core/src/test/resources/testdata/include-prop.copy.template diff --git a/testdata/include-prop.in.md b/kotlinx-knit-core/src/test/resources/testdata/include-prop.in.md similarity index 100% rename from testdata/include-prop.in.md rename to kotlinx-knit-core/src/test/resources/testdata/include-prop.in.md diff --git a/testdata/include-prop.properties b/kotlinx-knit-core/src/test/resources/testdata/include-prop.properties similarity index 100% rename from testdata/include-prop.properties rename to kotlinx-knit-core/src/test/resources/testdata/include-prop.properties diff --git a/testdata/include-prop/example-include-01.kt b/kotlinx-knit-core/src/test/resources/testdata/include-prop/example-include-01.kt similarity index 100% rename from testdata/include-prop/example-include-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/include-prop/example-include-01.kt diff --git a/testdata/pattern-prop.in.md b/kotlinx-knit-core/src/test/resources/testdata/pattern-prop.in.md similarity index 100% rename from testdata/pattern-prop.in.md rename to kotlinx-knit-core/src/test/resources/testdata/pattern-prop.in.md diff --git a/testdata/pattern-prop.out.md b/kotlinx-knit-core/src/test/resources/testdata/pattern-prop.out.md similarity index 100% rename from testdata/pattern-prop.out.md rename to kotlinx-knit-core/src/test/resources/testdata/pattern-prop.out.md diff --git a/testdata/pattern-prop.properties b/kotlinx-knit-core/src/test/resources/testdata/pattern-prop.properties similarity index 100% rename from testdata/pattern-prop.properties rename to kotlinx-knit-core/src/test/resources/testdata/pattern-prop.properties diff --git a/testdata/pattern-prop/pattern-001.kt b/kotlinx-knit-core/src/test/resources/testdata/pattern-prop/pattern-001.kt similarity index 100% rename from testdata/pattern-prop/pattern-001.kt rename to kotlinx-knit-core/src/test/resources/testdata/pattern-prop/pattern-001.kt diff --git a/testdata/test-basic.in.md b/kotlinx-knit-core/src/test/resources/testdata/test-basic.in.md similarity index 100% rename from testdata/test-basic.in.md rename to kotlinx-knit-core/src/test/resources/testdata/test-basic.in.md diff --git a/testdata/test-basic.properties b/kotlinx-knit-core/src/test/resources/testdata/test-basic.properties similarity index 100% rename from testdata/test-basic.properties rename to kotlinx-knit-core/src/test/resources/testdata/test-basic.properties diff --git a/testdata/test-basic/example-basic-01.kt b/kotlinx-knit-core/src/test/resources/testdata/test-basic/example-basic-01.kt similarity index 100% rename from testdata/test-basic/example-basic-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-basic/example-basic-01.kt diff --git a/testdata/test-basic/test/BasicTest.kt b/kotlinx-knit-core/src/test/resources/testdata/test-basic/test/BasicTest.kt similarity index 100% rename from testdata/test-basic/test/BasicTest.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-basic/test/BasicTest.kt diff --git a/testdata/test-hidden.in.md b/kotlinx-knit-core/src/test/resources/testdata/test-hidden.in.md similarity index 100% rename from testdata/test-hidden.in.md rename to kotlinx-knit-core/src/test/resources/testdata/test-hidden.in.md diff --git a/testdata/test-hidden.properties b/kotlinx-knit-core/src/test/resources/testdata/test-hidden.properties similarity index 100% rename from testdata/test-hidden.properties rename to kotlinx-knit-core/src/test/resources/testdata/test-hidden.properties diff --git a/testdata/test-hidden/example-hidden-01.kt b/kotlinx-knit-core/src/test/resources/testdata/test-hidden/example-hidden-01.kt similarity index 100% rename from testdata/test-hidden/example-hidden-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-hidden/example-hidden-01.kt diff --git a/testdata/test-hidden/test/BasicTest.kt b/kotlinx-knit-core/src/test/resources/testdata/test-hidden/test/BasicTest.kt similarity index 100% rename from testdata/test-hidden/test/BasicTest.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-hidden/test/BasicTest.kt diff --git a/testdata/test-lines-start.in.md b/kotlinx-knit-core/src/test/resources/testdata/test-lines-start.in.md similarity index 100% rename from testdata/test-lines-start.in.md rename to kotlinx-knit-core/src/test/resources/testdata/test-lines-start.in.md diff --git a/testdata/test-lines-start.properties b/kotlinx-knit-core/src/test/resources/testdata/test-lines-start.properties similarity index 100% rename from testdata/test-lines-start.properties rename to kotlinx-knit-core/src/test/resources/testdata/test-lines-start.properties diff --git a/testdata/test-lines-start/example-lines-start-01.kt b/kotlinx-knit-core/src/test/resources/testdata/test-lines-start/example-lines-start-01.kt similarity index 100% rename from testdata/test-lines-start/example-lines-start-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-lines-start/example-lines-start-01.kt diff --git a/testdata/test-lines-start/test/LinesStartTest.kt b/kotlinx-knit-core/src/test/resources/testdata/test-lines-start/test/LinesStartTest.kt similarity index 100% rename from testdata/test-lines-start/test/LinesStartTest.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-lines-start/test/LinesStartTest.kt diff --git a/testdata/test-predicate.in.md b/kotlinx-knit-core/src/test/resources/testdata/test-predicate.in.md similarity index 100% rename from testdata/test-predicate.in.md rename to kotlinx-knit-core/src/test/resources/testdata/test-predicate.in.md diff --git a/testdata/test-predicate.properties b/kotlinx-knit-core/src/test/resources/testdata/test-predicate.properties similarity index 100% rename from testdata/test-predicate.properties rename to kotlinx-knit-core/src/test/resources/testdata/test-predicate.properties diff --git a/testdata/test-predicate/example-predicate-01.kt b/kotlinx-knit-core/src/test/resources/testdata/test-predicate/example-predicate-01.kt similarity index 100% rename from testdata/test-predicate/example-predicate-01.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-predicate/example-predicate-01.kt diff --git a/testdata/test-predicate/test/PredicateTest.kt b/kotlinx-knit-core/src/test/resources/testdata/test-predicate/test/PredicateTest.kt similarity index 100% rename from testdata/test-predicate/test/PredicateTest.kt rename to kotlinx-knit-core/src/test/resources/testdata/test-predicate/test/PredicateTest.kt diff --git a/testdata/toc-forbidden-symbols.in.md b/kotlinx-knit-core/src/test/resources/testdata/toc-forbidden-symbols.in.md similarity index 100% rename from testdata/toc-forbidden-symbols.in.md rename to kotlinx-knit-core/src/test/resources/testdata/toc-forbidden-symbols.in.md diff --git a/testdata/toc-forbidden-symbols.out.md b/kotlinx-knit-core/src/test/resources/testdata/toc-forbidden-symbols.out.md similarity index 100% rename from testdata/toc-forbidden-symbols.out.md rename to kotlinx-knit-core/src/test/resources/testdata/toc-forbidden-symbols.out.md diff --git a/kotlinx-knit-dokka/build.gradle.kts b/kotlinx-knit-dokka/build.gradle.kts new file mode 100644 index 0000000..0392986 --- /dev/null +++ b/kotlinx-knit-dokka/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + buildsrc.conventions.`kotlin-jvm` + buildsrc.conventions.`maven-publish` +} + +dependencies { + implementation(platform(libs.jackson.bom)) + implementation(libs.jackson.kotlin) + implementation(libs.jackson.xml) + + implementation(libs.dokka.base) + implementation(libs.dokka.templatingPlugin) + compileOnly(libs.dokka.core) + + testImplementation(kotlin("test-junit5")) +} + +publishing { + publications { + register("dokkaPlugin") { + artifactId = "kotlinx-knit-dokka" + from(components["java"]) + } + } +} diff --git a/pathsaver/src/main/kotlin/PathsaverPlugin.kt b/kotlinx-knit-dokka/src/main/kotlin/PathsaverPlugin.kt similarity index 98% rename from pathsaver/src/main/kotlin/PathsaverPlugin.kt rename to kotlinx-knit-dokka/src/main/kotlin/PathsaverPlugin.kt index 9bf612a..acd9ba5 100644 --- a/pathsaver/src/main/kotlin/PathsaverPlugin.kt +++ b/kotlinx-knit-dokka/src/main/kotlin/PathsaverPlugin.kt @@ -1,7 +1,7 @@ -package kotlinx.knit.pathsaver +package kotlinx.knit.dokka import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import kotlinx.knit.pathsaver.DocumentableType.Companion.type +import kotlinx.knit.dokka.DocumentableType.Companion.type import org.jetbrains.dokka.CoreExtensions import org.jetbrains.dokka.DokkaConfiguration.DokkaModuleDescription import org.jetbrains.dokka.base.DokkaBase diff --git a/kotlinx-knit-dokka/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/kotlinx-knit-dokka/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin new file mode 100644 index 0000000..1d8f12c --- /dev/null +++ b/kotlinx-knit-dokka/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin @@ -0,0 +1 @@ +kotlinx.knit.dokka.PathsaverPlugin diff --git a/kotlinx-knit-gradle/build.gradle.kts b/kotlinx-knit-gradle/build.gradle.kts new file mode 100644 index 0000000..5a49392 --- /dev/null +++ b/kotlinx-knit-gradle/build.gradle.kts @@ -0,0 +1,45 @@ +plugins { + buildsrc.conventions.base + buildsrc.conventions.`kotlin-jvm` + `kotlin-dsl` + com.gradle.`plugin-publish` +} + +dependencies { + implementation(projects.kotlinxKnitCore) + + implementation(libs.freemarker) + implementation(libs.dokka.core) + + testImplementation(projects.kotlinxKnitTest) + testImplementation(kotlin("test-junit5")) +} + +gradlePlugin { + plugins { + create("kotlinx-knit") { + // This is a fully-qualified plugin id, short id of 'kotlinx-knit' is added manually in resources + id = "org.jetbrains.kotlinx.knit" + implementationClass = "kotlinx.knit.gradle.KnitPlugin" + displayName = "Knit documentation plugin" + description = + "Produces Kotlin source example files and tests from Markdown documents with embedded snippets of Kotlin code" + } + } +} + +pluginBundle { + website = "https://github.com/Kotlin/kotlinx-knit" + vcsUrl = "https://github.com/Kotlin/kotlinx-knit" + tags = listOf("kotlin", "documentation", "markdown") +} + +publishing { + repositories { + // see buildsrc.conventions.`maven-publish` plugin + // (copied here because the Gradle publish plugin isn't compatible with the convention plugin.) + maven(rootProject.layout.buildDirectory.dir("maven-project-local")) { + name = "MavenProjectLocal" + } + } +} diff --git a/kotlinx-knit-gradle/src/main/kotlin/KnitPlugin.kt b/kotlinx-knit-gradle/src/main/kotlin/KnitPlugin.kt new file mode 100644 index 0000000..f47d118 --- /dev/null +++ b/kotlinx-knit-gradle/src/main/kotlin/KnitPlugin.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.knit.gradle + +import kotlinx.knit.globalDefaults +import org.gradle.api.DefaultTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.attributes.Usage +import org.gradle.api.logging.Logging +import org.gradle.api.model.ObjectFactory +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.withType +import org.gradle.language.base.plugins.LifecycleBasePlugin +import javax.inject.Inject + + +abstract class KnitPlugin @Inject constructor( + private val objects: ObjectFactory, +) : Plugin { + + private val logger = Logging.getLogger(KnitPlugin::class.java) + + override fun apply(project: Project) { + val extension = project.createExtension() + + val knitPrepare = project.tasks.register("knitPrepare") { + description = "Prepares dependencies for Knit tool" + group = TASK_GROUP + } + + project.tasks.withType().configureEach { + group = TASK_GROUP + check.convention(false) + rootDir.convention(extension.rootDir) + files.from(extension.files) + } + + val knitCheck = project.tasks.register(TASK_NAME_KNIT_CHECK) { + description = "Runs Knit tool check (does not modify anything)" + check.convention(true) + dependsOn(knitPrepare) + } + + project.tasks.register(TASK_NAME_KNIT) { + description = "Runs Knit tool" + dependsOn(knitPrepare) + } + + project.plugins.withType { + project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).configure { + dependsOn(knitCheck) + } + } + + project.configurations.register("knitRuntimeClasspath") { + isCanBeResolved = true + isCanBeConsumed = false + isVisible = false + + attributes { + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) + } + + defaultDependencies { + project.dependencies.create( + extension.knitVersion.map { ver -> "org.jetbrains.kotlinx:kotlinx-knit-test:$ver" } + ) + } + } + + // Configure default version resolution for 'kotlinx-knit-test' + +// val pluginVersion = project.rootProject.buildscript.configurations.findByName("classpath") +// ?.allDependencies?.find { it.group == DEPENDENCY_GROUP && it.name == "kotlinx-knit" }?.version +// +// logger.debug("Knit plugin version: $pluginVersion") +// +// if (pluginVersion != null) { +// project.configurations.all { +// resolutionStrategy.eachDependency { +// if (requested.group == DEPENDENCY_GROUP && requested.name == "kotlinx-knit-test" && requested.version == null) { +// useVersion(pluginVersion) +// } +// } +// } +// } + } + + private fun Project.createExtension(): KnitPluginExtension { + return extensions.create(EXTENSION_NAME, KnitPluginExtension::class).apply { + siteRoot.convention(globalDefaults.siteRoot) + moduleRoots.convention(globalDefaults.moduleRoots) + moduleMarkers.convention(globalDefaults.moduleMarkers) + moduleDocs.convention(globalDefaults.moduleDocs) + dokkaMultiModuleRoot.convention(globalDefaults.dokkaMultiModuleRoot) + rootDir.convention(layout.projectDirectory.file(".")) + files.from(layout.projectDirectory.asFileTree.matching { + include("**/*.md") + include("**/*.kt") + include("**/*.kts") + exclude("**/build/*", "**/.gradle/*") + }) + } + } + + companion object { + const val TASK_GROUP = JavaBasePlugin.DOCUMENTATION_GROUP + const val DEPENDENCY_GROUP = "org.jetbrains.kotlinx" + const val EXTENSION_NAME = "knit" + const val TASK_NAME_KNIT = "knit" + const val TASK_NAME_KNIT_CHECK = "knit" + } +} diff --git a/kotlinx-knit-gradle/src/main/kotlin/KnitPluginExtension.kt b/kotlinx-knit-gradle/src/main/kotlin/KnitPluginExtension.kt new file mode 100644 index 0000000..999093f --- /dev/null +++ b/kotlinx-knit-gradle/src/main/kotlin/KnitPluginExtension.kt @@ -0,0 +1,51 @@ +package kotlinx.knit.gradle + +import kotlinx.knit.* +import org.gradle.api.GradleException +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.* +import java.io.File + +abstract class KnitPluginExtension { + abstract val knitVersion: Property + abstract val siteRoot: Property + abstract val moduleRoots: ListProperty + abstract val moduleMarkers: ListProperty + abstract val moduleDocs: Property + abstract val files: ConfigurableFileCollection + abstract val rootDir: RegularFileProperty + abstract val dokkaMultiModuleRoot: Property + abstract val defaultLineSeparator: Property + + fun createContext(files: Collection, rootDir: File, check: Boolean) = KnitContext( + log = LoggerLog(), + globals = KnitGlobals( + siteRoot = siteRoot.get(), + moduleRoots = moduleRoots.get(), + moduleMarkers = moduleMarkers.get(), + moduleDocs = moduleDocs.get(), + dokkaMultiModuleRoot = dokkaMultiModuleRoot.get(), + ), + files = files, + rootDir = rootDir, + lineSeparator = evaluateLineSeparator(), + check = check + ) + + private fun evaluateLineSeparator(): String { + val unix = "\n" + val windows = "\r\n" + val ls = defaultLineSeparator.orNull + if (ls != null && ls != unix && ls != windows) { + throw GradleException( + """ + |Knit defaultLineSeparator must be one of: + |- Unix (\n) + |- Windows (\r\n) + """.trimMargin() + ) + } + return ls ?: unix + } +} diff --git a/kotlinx-knit-gradle/src/main/kotlin/KnitTask.kt b/kotlinx-knit-gradle/src/main/kotlin/KnitTask.kt new file mode 100644 index 0000000..d08b495 --- /dev/null +++ b/kotlinx-knit-gradle/src/main/kotlin/KnitTask.kt @@ -0,0 +1,42 @@ +package kotlinx.knit.gradle + +import kotlinx.knit.process +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.getByType + + +abstract class KnitTask : DefaultTask() { + private val ext: KnitPluginExtension = project.extensions.getByType() + + @get:Input + @get:Optional + abstract val check: Property + + @get:Internal + abstract val rootDir: RegularFileProperty + + @get:InputFiles + abstract val files: ConfigurableFileCollection + + @TaskAction + fun knit() { + val rootDirFile = rootDir.asFile.get() + val checkEnabled = check.getOrElse(false) + + val ctx = ext.createContext(files.files, rootDirFile, checkEnabled) + + if (!ctx.process() || checkEnabled && ctx.log.hasWarningOrError) { + val extra = if (ctx.log.nOutdated > 0) { + "\nRun 'knit' task to write ${ctx.log.nOutdated} missing/outdated files." + } else { + "" + } + throw GradleException("$name task failed, see log for details (use '--info' for detailed log).$extra") + } + } +} diff --git a/resources/META-INF/gradle-plugins/kotlinx-knit.properties b/kotlinx-knit-gradle/src/main/resources/META-INF/gradle-plugins/kotlinx-knit.properties similarity index 100% rename from resources/META-INF/gradle-plugins/kotlinx-knit.properties rename to kotlinx-knit-gradle/src/main/resources/META-INF/gradle-plugins/kotlinx-knit.properties diff --git a/kotlinx-knit-test/build.gradle.kts b/kotlinx-knit-test/build.gradle.kts index a481aa5..c072a1f 100644 --- a/kotlinx-knit-test/build.gradle.kts +++ b/kotlinx-knit-test/build.gradle.kts @@ -1,43 +1,46 @@ -import kotlinx.knit.build.* - plugins { + buildsrc.conventions.`kotlin-jvm` + buildsrc.conventions.`maven-publish` id("org.jetbrains.dokka") - signing - `maven-publish` + buildsrc.conventions.`dokka-docs-share` } -tasks { - val dokkaVersion: String by project - - val dokka by creating { - dependsOn(dokkaJekyll) - } +val dokka: Task by tasks.creating { + dependsOn(tasks.dokkaJekyll) +} - dokkaJekyll { - outputDirectory.set(file("$buildDir/dokka")) - } +tasks.dokkaJekyll { + outputDirectory.set(file("$buildDir/dokka")) +} - dokkaHtml { - outputDirectory.set(file("$buildDir/dokkaHtml")) - } +tasks.dokkaHtml { + outputDirectory.set(file("$buildDir/dokkaHtml")) } dependencies { - dokkaHtmlPlugin(project(":pathsaver")) - dokkaJekyllPlugin(project(":pathsaver")) + dokkaHtmlPlugin(projects.kotlinxKnitDokka) + dokkaJekyllPlugin(projects.kotlinxKnitDokka) + + testImplementation(kotlin("test-junit5")) } publishing { publications { create("kotlinxKnitTest") { + artifactId = "knit-test" from(components["java"]) - mavenCentralArtifacts(project, project.sourceSets.main.allSource) } } +} - mavenCentralMetadata() - mavenRepositoryPublishing(project) - publications.withType(MavenPublication::class).all { - signPublicationIfKeyPresent(this) - } +val dokkaHtmlSync by tasks.registering(Sync::class) { + // Dokka doesn't correct cache tasks, so to prevent unnecessary work manually cache + // dokkaHtml task with this sync task. Since Dokka is slow, this helps build speed. + from(tasks.dokkaHtml) + into(temporaryDir) +} + +configurations.dokkaHtmlDocsElements { + // share Dokka HTML with other subprojects + outgoing { artifact(dokkaHtmlSync) } } diff --git a/kotlinx-knit-test/src/KnitDiff.kt b/kotlinx-knit-test/src/main/kotlin/KnitDiff.kt similarity index 100% rename from kotlinx-knit-test/src/KnitDiff.kt rename to kotlinx-knit-test/src/main/kotlin/KnitDiff.kt diff --git a/kotlinx-knit-test/src/KnitTest.kt b/kotlinx-knit-test/src/main/kotlin/KnitTest.kt similarity index 100% rename from kotlinx-knit-test/src/KnitTest.kt rename to kotlinx-knit-test/src/main/kotlin/KnitTest.kt diff --git a/kotlinx-knit-test/test/CaptureOutputTest.kt b/kotlinx-knit-test/src/test/kotlin/CaptureOutputTest.kt similarity index 100% rename from kotlinx-knit-test/test/CaptureOutputTest.kt rename to kotlinx-knit-test/src/test/kotlin/CaptureOutputTest.kt diff --git a/kotlinx-knit-test/test/DiffTest.kt b/kotlinx-knit-test/src/test/kotlin/DiffTest.kt similarity index 99% rename from kotlinx-knit-test/test/DiffTest.kt rename to kotlinx-knit-test/src/test/kotlin/DiffTest.kt index 25719ab..53b9ce9 100644 --- a/kotlinx-knit-test/test/DiffTest.kt +++ b/kotlinx-knit-test/src/test/kotlin/DiffTest.kt @@ -4,7 +4,6 @@ package kotlinx.knit.test -import org.junit.Test import kotlin.random.* import kotlin.test.* @@ -244,4 +243,4 @@ class DiffTest { val newLines = rndLines() assertNull(compute(oldLines, newLines)) } -} \ No newline at end of file +} diff --git a/pathsaver/build.gradle.kts b/pathsaver/build.gradle.kts deleted file mode 100644 index c9db1fb..0000000 --- a/pathsaver/build.gradle.kts +++ /dev/null @@ -1,33 +0,0 @@ -import com.gradle.publish.* -import kotlinx.knit.build.* - -plugins { - java - signing - `maven-publish` -} - -val dokkaVersion: String by project - -dependencies { - implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.11.1") - implementation("org.jetbrains.dokka:dokka-base:$dokkaVersion") - implementation("org.jetbrains.dokka:templating-plugin:$dokkaVersion") - compileOnly("org.jetbrains.dokka:dokka-core:$dokkaVersion") -} - -publishing { - publications { - register("dokkaPlugin") { - artifactId = "dokka-pathsaver-plugin" - from(components["java"]) - mavenCentralArtifacts(project, project.sourceSets.main.allSource) - } - } - - mavenCentralMetadata() - mavenRepositoryPublishing(project) - publications.withType(MavenPublication::class).all { - signPublicationIfKeyPresent(this) - } -} diff --git a/pathsaver/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/pathsaver/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin deleted file mode 100644 index c75d649..0000000 --- a/pathsaver/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin +++ /dev/null @@ -1 +0,0 @@ -kotlinx.knit.pathsaver.PathsaverPlugin diff --git a/settings.gradle.kts b/settings.gradle.kts index 07c5176..163555b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,26 +3,16 @@ */ rootProject.name = "kotlinx-knit" -include("kotlinx-knit-test") -include("pathsaver") -pluginManagement { - repositories { - maven(url = "https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev/") - gradlePluginPortal() - } - resolutionStrategy { - val kotlinVersion: String by settings - val dokkaVersion: String by settings - val pluginPublishVersion: String by settings +apply(from = "buildSrc/repositories.settings.gradle.kts") - eachPlugin { - val id = requested.id.id - when { - id.startsWith("org.jetbrains.kotlin.") -> useVersion(kotlinVersion) - id == "org.jetbrains.dokka" -> useVersion(dokkaVersion) - id == "com.gradle.plugin-publish" -> useVersion(pluginPublishVersion) - } - } - } -} + +include( + ":kotlinx-knit-core", + ":kotlinx-knit-dokka", + ":kotlinx-knit-gradle", + ":kotlinx-knit-test", +) + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") diff --git a/src/KnitPlugin.kt b/src/KnitPlugin.kt deleted file mode 100644 index 6bd25de..0000000 --- a/src/KnitPlugin.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.knit - -import org.apache.log4j.* -import org.gradle.api.* -import org.gradle.api.file.* -import org.gradle.api.tasks.* -import java.io.* - -const val TASK_GROUP = "documentation" -const val DEPENDENCY_GROUP = "org.jetbrains.kotlinx" - -class KnitPlugin : Plugin { - override fun apply(project: Project): Unit = with(project) { - // Create tasks - extensions.create("knit", KnitPluginExtension::class.java) - val knitPrepare = tasks.register("knitPrepare", DefaultTask::class.java) { - it.description = "Prepares dependencies for Knit tool" - it.group = TASK_GROUP - } - val knitCheck = tasks.register("knitCheck", KnitTask::class.java) { - it.description = "Runs Knit tool check (does not modify anything)" - it.group = TASK_GROUP - it.check = true - it.dependsOn(knitPrepare) - } - tasks.register("knit", KnitTask::class.java) { - it.description = "Runs Knit tool" - it.group = TASK_GROUP - it.dependsOn(knitPrepare) - } - checkDependsOn(knitCheck) - // Configure default version resolution for 'kotlinx-knit-test' - val pluginVersion = rootProject.buildscript.configurations.findByName("classpath") - ?.allDependencies?.find { it.group == DEPENDENCY_GROUP && it.name == "kotlinx-knit" }?.version - Logger.getLogger(KnitPlugin::class.java).debug("Plugin version: $pluginVersion") - if (pluginVersion != null) { - configurations.all { configuration -> - configuration.resolutionStrategy.eachDependency { dependency -> - val requested = dependency.requested - if (requested.group == DEPENDENCY_GROUP && requested.name == "kotlinx-knit-test" && requested.version == null) { - dependency.useVersion(pluginVersion) - } - } - } - } - } -} - -private fun Project.checkDependsOn(other: TaskProvider<*>) { - pluginManager.withPlugin("base") { - tasks.named("check").configure { - it.dependsOn(other) - } - } -} - -open class KnitTask : DefaultTask() { - private val ext: KnitPluginExtension = project.extensions.getByType(KnitPluginExtension::class.java) - - @Input - var check: Boolean = false - - @Internal - var rootDir: File = ext.rootDir ?: project.rootDir - - @Internal - var files: FileCollection = ext.files ?: project.fileTree(project.rootDir) { - it.include("**/*.md") - it.include("**/*.kt") - it.include("**/*.kts") - it.exclude("**/build/*") - it.exclude("**/.gradle/*") - } - - init { - outputs.upToDateWhen { false } - } - - @TaskAction - fun knit() { - val ctx = ext.createContext(files.files, rootDir, check) - if (!ctx.process() || check && ctx.log.hasWarningOrError) { - val extra = if (ctx.log.nOutdated > 0) - "\nRun 'knit' task to write ${ctx.log.nOutdated} missing/outdated files." - else - "" - throw GradleException("$name task failed, see log for details (use '--info' for detailed log).$extra") - } - } -} - -open class KnitPluginExtension { - var siteRoot: String? = globalDefaults.siteRoot - var moduleRoots: List = globalDefaults.moduleRoots - var moduleMarkers: List = globalDefaults.moduleMarkers - var moduleDocs: String = globalDefaults.moduleDocs - var files: FileCollection? = null - var rootDir: File? = null - var dokkaMultiModuleRoot: String = globalDefaults.dokkaMultiModuleRoot - var defaultLineSeparator: String? = null - - fun createContext(files: Collection, rootDir: File, check: Boolean) = KnitContext( - log = LoggerLog(), - globals = KnitGlobals( - siteRoot = siteRoot, - moduleRoots = moduleRoots, - moduleMarkers = moduleMarkers, - moduleDocs = moduleDocs, - dokkaMultiModuleRoot = dokkaMultiModuleRoot - ), - files = files, - rootDir = rootDir, - lineSeparator = evaluateLineSeparator(), - check = check - ) - - private fun evaluateLineSeparator(): String { - val unix = "\n" - val windows = "\r\n" - val ls = defaultLineSeparator - if (ls != null && ls != unix && ls != windows) { - throw GradleException( - """Knit defaultLineSeparator must be one of: - |- Unix (\n) - |- Windows (\r\n) - """.trimMargin() - ) - } - return ls ?: unix - } -} diff --git a/testdata/dokka-root.properties b/testdata/dokka-root.properties deleted file mode 100644 index f345299..0000000 --- a/testdata/dokka-root.properties +++ /dev/null @@ -1 +0,0 @@ -module.roots=kotlinx-knit-test \ No newline at end of file