diff options
132 files changed, 1737 insertions, 425 deletions
@@ -89,4 +89,6 @@ gradle-app.setting !lib/*.jar local.properties -android.local.properties
\ No newline at end of file +android.local.properties + +!runners/gradle-integration-tests/testData/basic/classDir/**/*.class
\ No newline at end of file @@ -72,7 +72,7 @@ dokka { skipDeprecated = false // Emit warnings about not documented members. Applies globally, also can be overridden by packageOptions - reportNotDocumented = true + reportUndocumented = true skipEmptyPackages = true // Do not create index pages for empty packages @@ -132,6 +132,11 @@ dokka { reportUndocumented = true // Emit warnings about not documented members includeNonPublic = false } + // Suppress a package + packageOptions { + prefix = "kotlin.internal" // will match kotlin.internal and all sub-packages of it + suppress = true + } } ``` diff --git a/build.gradle b/build.gradle index 9d081673..f1748259 100644 --- a/build.gradle +++ b/build.gradle @@ -1,35 +1,39 @@ +import org.jetbrains.DependenciesVersionGetter + allprojects { group 'org.jetbrains.dokka' version dokka_version + def repo = { + artifactPattern("https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/[revision]/internal/[module](.[ext])") + artifactPattern("https://teamcity.jetbrains.com/guestAuth/repository/download/IntelliJMarkdownParser_Build/[revision]/([module]_[ext]/)[module](.[ext])") + } + buildscript { repositories { mavenCentral() jcenter() - maven { - url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" - } - maven { - url "https://dl.bintray.com/kotlin/kotlin-dev" - } - maven { - url "https://plugins.gradle.org/m2/" - } + maven { url "http://dl.bintray.com/kotlin/kotlin-eap" } + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } + maven { url "https://plugins.gradle.org/m2/" } + ivy(repo) } dependencies { classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1' - classpath "com.gradle.publish:plugin-publish-plugin:0.9.6" + classpath "com.gradle.publish:plugin-publish-plugin:0.9.10" } } repositories { mavenCentral() mavenLocal() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "http://dl.bintray.com/kotlin/kotlin-eap" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } maven { url 'https://jitpack.io' } + maven { url "https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/$bundled_kotlin_compiler_version/maven" } + ivy(repo) } } @@ -60,6 +64,38 @@ def bintrayPublication(project, List<String> _publications) { } task wrapper(type: Wrapper) { - gradleVersion = '4.2' + gradleVersion = '4.2.1' distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" +} + +def versions = DependenciesVersionGetter.getVersions(project, bundled_kotlin_compiler_version) + +ext.ideaVersion = versions["idea.build.id"] +ext.markdownVersion = versions["markdown.build.id"].replace("%20", " ") + +configurations { + ideaIC + intellijCore +} + +repositories { + maven { url 'https://www.jetbrains.com/intellij-repository/snapshots' } + maven { url 'https://www.jetbrains.com/intellij-repository/releases' } +} + +dependencies { + intellijCore "com.jetbrains.intellij.idea:intellij-core:$ideaVersion" + ideaIC "com.jetbrains.intellij.idea:ideaIC:$ideaVersion" +} + +def intellijCoreAnalysis() { + return zipTree(configurations.intellijCore.singleFile).matching ({ + include("intellij-core-analysis.jar") + }) +} + +def ideaRT() { + return zipTree(project.configurations.ideaIC.singleFile).matching ({ + include("lib/idea_rt.jar") + }) }
\ No newline at end of file diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 76c7c4ee..874dabc9 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -2,12 +2,8 @@ apply plugin: 'groovy' repositories { mavenCentral() jcenter() - maven { - url "https://dl.bintray.com/kotlin/kotlin-eap" - } - maven { - url "https://dl.bintray.com/kotlin/kotlin-dev" - } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { compile 'com.github.jengelman.gradle.plugins:shadow:2.0.1' diff --git a/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy b/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy new file mode 100644 index 00000000..3e1d2106 --- /dev/null +++ b/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy @@ -0,0 +1,39 @@ +package org.jetbrains + +import org.gradle.api.Project +import org.gradle.api.artifacts.ModuleVersionIdentifier +import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.artifacts.SelfResolvingDependency +import org.gradle.api.publish.internal.ProjectDependencyPublicationResolver +import org.gradle.api.publish.maven.MavenPom +import org.gradle.api.publish.maven.MavenPublication + +static void configure(MavenPublication publication, Project project) { + publication.artifact(project.tasks.shadowJar) + + publication.pom { MavenPom pom -> + pom.withXml { xml -> + def dependenciesNode = xml.asNode().appendNode('dependencies') + + project.configurations.shadow.allDependencies.each { + //if (! (it instanceof SelfResolvingDependency)) { + if (it instanceof ProjectDependency) { + def projectDependencyResolver = project.gradle.services.get(ProjectDependencyPublicationResolver) + ModuleVersionIdentifier identifier = projectDependencyResolver.resolve(it) + addDependency(dependenciesNode, identifier) + } else if (!(it instanceof SelfResolvingDependency)) { + addDependency(dependenciesNode, it) + } + + } + } + } +} + +private static void addDependency(Node dependenciesNode, dep) { + def dependencyNode = dependenciesNode.appendNode('dependency') + dependencyNode.appendNode('groupId', dep.group) + dependencyNode.appendNode('artifactId', dep.name) + dependencyNode.appendNode('version', dep.version) + dependencyNode.appendNode('scope', 'runtime') +}
\ No newline at end of file diff --git a/buildSrc/src/main/groovy/org/jetbrains/DependenciesVersionGetter.groovy b/buildSrc/src/main/groovy/org/jetbrains/DependenciesVersionGetter.groovy new file mode 100644 index 00000000..194f11af --- /dev/null +++ b/buildSrc/src/main/groovy/org/jetbrains/DependenciesVersionGetter.groovy @@ -0,0 +1,14 @@ +package org.jetbrains + +import org.gradle.api.Project + +class DependenciesVersionGetter { + static Properties getVersions(Project project, String artifactVersionSelector) { + def dep = project.dependencies.create(group: 'teamcity', name: 'dependencies', version: artifactVersionSelector, ext: 'properties') + def file = project.configurations.detachedConfiguration(dep).resolve().first() + + def prop = new Properties() + prop.load(new FileReader(file)) + return prop + } +} diff --git a/buildSrc/src/main/groovy/org/jetbrains/PluginXmlTransformer.groovy b/buildSrc/src/main/groovy/org/jetbrains/PluginXmlTransformer.groovy index 7482a01a..e711388f 100644 --- a/buildSrc/src/main/groovy/org/jetbrains/PluginXmlTransformer.groovy +++ b/buildSrc/src/main/groovy/org/jetbrains/PluginXmlTransformer.groovy @@ -1,5 +1,6 @@ package org.jetbrains +import com.github.jengelman.gradle.plugins.shadow.relocation.RelocateClassContext import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext @@ -22,7 +23,7 @@ public class PluginXmlTransformer implements Transformer { def inputStream = context.is System.out.println(path) Node node = new XmlParser().parse(inputStream) - relocateXml(node, context.relocators) + relocateXml(node, context) transformedPluginXmlFiles.put(path, node) } @@ -39,28 +40,32 @@ public class PluginXmlTransformer implements Transformer { } } - private static void relocateXml(Node node, List<Relocator> relocators) { + private static void relocateXml(Node node, TransformerContext context) { Map attributes = node.attributes() + RelocateClassContext relocateClassContext = new RelocateClassContext() + relocateClassContext.stats = context.stats for (Map.Entry entry : attributes.entrySet()) { - entry.setValue(relocateClassName((String) entry.getValue(), relocators)) + relocateClassContext.setClassName((String) entry.getValue()) + entry.setValue(relocateClassName(relocateClassContext, context)) } List<String> localText = node.localText() if (localText.size() == 1) { - node.setValue(relocateClassName(localText[0], relocators)) + relocateClassContext.setClassName(localText[0]) + node.setValue(relocateClassName(relocateClassContext, context)) } node.children().each { if (it instanceof Node) { - relocateXml((Node) it, relocators) + relocateXml((Node) it, context) } } } - private static String relocateClassName(String className, List<Relocator> relocators) { - for (Relocator relocator : relocators) { - if (relocator.canRelocateClass(className)) { - return relocator.relocateClass(className) + private static String relocateClassName(RelocateClassContext relocateContext, TransformerContext context) { + for (Relocator relocator : context.relocators) { + if (relocator.canRelocateClass(relocateContext)) { + return relocator.relocateClass(relocateContext) } } - return className + return relocateContext.className } }
\ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index c705e2cf..1a93bb48 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,21 +8,30 @@ buildscript { apply plugin: 'kotlin' -sourceCompatibility = 1.6 +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + languageVersion = "1.2" + apiVersion = languageVersion + jvmTarget = "1.8" + } +} dependencies { - compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_version - compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_version + compile "org.jetbrains.kotlin:kotlin-stdlib:$bundled_kotlin_compiler_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$bundled_kotlin_compiler_version" compile group: 'com.google.inject', name: 'guice', version: '3.0' compile "org.jsoup:jsoup:1.8.3" - compile files("../lib/intellij-core-analysis.jar") + compile "org.jetbrains.kotlin:kotlin-compiler:$bundled_kotlin_compiler_version" + compile "org.jetbrains.kotlin:kotlin-script-runtime:$bundled_kotlin_compiler_version" - compile group: 'org.jetbrains.kotlin', name: 'kotlin-compiler', version: kotlin_version - compile group: 'org.jetbrains.kotlin', name: 'kotlin-script-runtime', version: kotlin_version - compile files("../lib/kotlin-ide-common.jar") - compile files("../lib/markdown.jar") + compile "teamcity:kotlin-ide-common:$bundled_kotlin_compiler_version" + compile "teamcity:markdown:$markdownVersion" + + compile intellijCoreAnalysis() //tools.jar def toolsJar = files(((URLClassLoader) ToolProvider.getSystemToolClassLoader()).getURLs().findAll { it.path.endsWith("jar") }) @@ -34,5 +43,6 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlin_version testCompile "com.nhaarman:mockito-kotlin-kt1.1:1.5.0" -} + testCompile ideaRT() +}
\ No newline at end of file diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index be4285c0..5522d4f0 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import com.google.common.collect.ImmutableMap import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreModuleManager import com.intellij.mock.MockComponentManager @@ -13,11 +14,11 @@ import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles @@ -35,16 +36,19 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.JvmBuiltIns -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice +import org.jetbrains.kotlin.util.slicedMap.WritableSlice import java.io.File /** @@ -114,11 +118,17 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { val builtIns = JvmBuiltIns(projectContext.storageManager) - val javaRoots = run { - val jvfs = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JAR_PROTOCOL) + val javaRoots = classpath + .mapNotNull { + val rootFile = when { + it.extension == "jar" -> + StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}") + else -> + StandardFileSystems.local().findFileByPath(it.absolutePath) + } - classpath.map { JavaRoot(jvfs.findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}")!!, JavaRoot.RootType.BINARY) } - } + rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } + } val resolverForProject = ResolverForProjectImpl( "Dokka", @@ -141,7 +151,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { }, CompilerEnvironment, packagePartProviderFactory = { info, content -> - JvmPackagePartProvider(LanguageVersionSettingsImpl.DEFAULT, content.moduleContentScope).apply { + JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { addRoots(javaRoots) } }, @@ -153,7 +163,17 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { val resolverForModule = resolverForProject.resolverForModule(module) val moduleDescriptor = resolverForProject.descriptorForModule(module) builtIns.initialize(moduleDescriptor, true) - return DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) + val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) + val projectComponentManager = environment.project as MockComponentManager + projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) + + return created + } + + fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { + val languageVersion = LanguageVersion.fromVersionString(languageVersionString) ?: LanguageVersion.LATEST_STABLE + val apiVersion = apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion) + configuration.languageVersionSettings = LanguageVersionSettingsImpl(languageVersion, apiVersion) } /** @@ -236,6 +256,42 @@ class DokkaResolutionFacade(override val project: Project, val resolveSession: ResolveSession get() = getFrontendService(ResolveSession::class.java) override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext { + if (element is KtDeclaration) { + val descriptor = resolveToDescriptor(element) + return object : BindingContext { + override fun <K : Any?, V : Any?> getKeys(p0: WritableSlice<K, V>?): Collection<K> { + throw UnsupportedOperationException() + } + + override fun getType(p0: KtExpression): KotlinType? { + throw UnsupportedOperationException() + } + + override fun <K : Any?, V : Any?> get(slice: ReadOnlySlice<K, V>?, key: K): V? { + if (key != element) { + throw UnsupportedOperationException() + } + return when { + slice == BindingContext.DECLARATION_TO_DESCRIPTOR -> descriptor as V + slice == BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER && (element as KtParameter).hasValOrVar() -> descriptor as V + else -> null + } + } + + override fun getDiagnostics(): Diagnostics { + throw UnsupportedOperationException() + } + + override fun addOwnDataTo(p0: BindingTrace, p1: Boolean) { + throw UnsupportedOperationException() + } + + override fun <K : Any?, V : Any?> getSliceContents(p0: ReadOnlySlice<K, V>): ImmutableMap<K, V> { + throw UnsupportedOperationException() + } + + } + } throw UnsupportedOperationException() } diff --git a/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt b/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt new file mode 100644 index 00000000..31b8ffc7 --- /dev/null +++ b/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt @@ -0,0 +1,30 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache + + +class CoreKotlinCacheService(private val resolutionFacade: DokkaResolutionFacade) : KotlinCacheService { + override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade { + return resolutionFacade + } + + override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade { + return resolutionFacade + } + + override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? { + return resolutionFacade + } + + override fun getSuppressionCache(): KotlinSuppressCache { + throw UnsupportedOperationException() + } + +} + diff --git a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt index 21f7e2da..4f6a7c76 100644 --- a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt +++ b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt @@ -32,7 +32,11 @@ import java.io.File * classes from projectModel-{api,impl}. */ class CoreProjectFileIndex(private val project: Project, contentRoots: List<ContentRoot>) : ProjectFileIndex, ModuleFileIndex { - override fun iterateContentUnderDirectory(p0: VirtualFile, p1: ContentIterator, p2: VirtualFileFilter): Boolean { + override fun iterateContent(p0: ContentIterator, p1: VirtualFileFilter?): Boolean { + throw UnsupportedOperationException() + } + + override fun iterateContentUnderDirectory(p0: VirtualFile, p1: ContentIterator, p2: VirtualFileFilter?): Boolean { throw UnsupportedOperationException() } @@ -74,7 +78,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont throw UnsupportedOperationException() } - override fun setOption(p0: String, p1: String) { + override fun setOption(p0: String, p1: String?) { throw UnsupportedOperationException() } @@ -224,24 +228,26 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont } private val moduleSourceOrderEntry = object : ModuleSourceOrderEntry { - override fun getFiles(p0: OrderRootType?): Array<out VirtualFile> { + override fun getFiles(p0: OrderRootType): Array<VirtualFile> { throw UnsupportedOperationException() } - override fun getPresentableName(): String { + override fun getUrls(p0: OrderRootType): Array<String> { throw UnsupportedOperationException() } - override fun getUrls(p0: OrderRootType?): Array<out String> { + override fun <R : Any?> accept(p0: RootPolicy<R>, p1: R?): R { throw UnsupportedOperationException() } - override fun getOwnerModule(): Module = module - override fun <R : Any?> accept(p0: RootPolicy<R>?, p1: R?): R { + override fun getPresentableName(): String { throw UnsupportedOperationException() } + override fun getOwnerModule(): Module = module + + override fun isValid(): Boolean { throw UnsupportedOperationException() } @@ -258,29 +264,29 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont } private val sdkOrderEntry = object : JdkOrderEntry { - override fun getJdkName(): String? { + override fun getFiles(p0: OrderRootType): Array<VirtualFile> { throw UnsupportedOperationException() } - override fun getJdk(): Sdk = sdk - - override fun getFiles(p0: OrderRootType?): Array<out VirtualFile> { + override fun getUrls(p0: OrderRootType): Array<String> { throw UnsupportedOperationException() } - override fun getPresentableName(): String { + override fun <R : Any?> accept(p0: RootPolicy<R>, p1: R?): R { throw UnsupportedOperationException() } - override fun getUrls(p0: OrderRootType?): Array<out String> { + override fun getJdkName(): String? { throw UnsupportedOperationException() } - override fun getOwnerModule(): Module { + override fun getJdk(): Sdk = sdk + + override fun getPresentableName(): String { throw UnsupportedOperationException() } - override fun <R : Any?> accept(p0: RootPolicy<R>?, p1: R?): R { + override fun getOwnerModule(): Module { throw UnsupportedOperationException() } @@ -288,11 +294,11 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont throw UnsupportedOperationException() } - override fun getRootFiles(p0: OrderRootType?): Array<out VirtualFile>? { + override fun getRootFiles(p0: OrderRootType): Array<out VirtualFile> { throw UnsupportedOperationException() } - override fun getRootUrls(p0: OrderRootType?): Array<out String>? { + override fun getRootUrls(p0: OrderRootType): Array<out String> { throw UnsupportedOperationException() } @@ -307,6 +313,10 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont } inner class MyModuleRootManager : ModuleRootManager() { + override fun getExternalSource(): ProjectModelExternalSource? { + throw UnsupportedOperationException() + } + override fun getExcludeRoots(): Array<out VirtualFile> { throw UnsupportedOperationException() } @@ -350,7 +360,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont override fun getRootModel(p0: Module): ModuleRootModel = this@MyModuleRootManager }) - override fun <T : Any?> getModuleExtension(p0: Class<T>?): T { + override fun <T : Any?> getModuleExtension(p0: Class<T>): T { throw UnsupportedOperationException() } diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index e9d0f3d5..126a0175 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -17,7 +17,8 @@ fun parsePerPackageOptions(arg: String): List<PackageOptions> { val deprecated = args.find { it.endsWith("deprecated") }?.startsWith("+") ?: true val reportUndocumented = args.find { it.endsWith("warnUndocumented") }?.startsWith("+") ?: true val privateApi = args.find { it.endsWith("privateApi") }?.startsWith("+") ?: false - PackageOptionsImpl(prefix, includeNonPublic = privateApi, reportUndocumented = reportUndocumented, skipDeprecated = !deprecated) + val suppress = args.find { it.endsWith("suppress") }?.startsWith("+") ?: false + PackageOptionsImpl(prefix, includeNonPublic = privateApi, reportUndocumented = reportUndocumented, skipDeprecated = !deprecated, suppress = suppress) } } @@ -65,6 +66,8 @@ class DokkaBootstrapImpl : DokkaBootstrap { perPackageOptions, externalDocumentationLinks, noStdlibLink, + languageVersion, + apiVersion, cacheRoot, suppressedFiles.map { File(it) } ) diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt index fc925f40..da0156a7 100644 --- a/core/src/main/kotlin/Formats/FormatDescriptor.kt +++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka.Formats import org.jetbrains.dokka.* +import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.dokka.Samples.SampleProcessingService import kotlin.reflect.KClass @@ -12,4 +13,5 @@ interface FormatDescriptor { val javaDocumentationBuilderClass: KClass<out JavaDocumentationBuilder> val sampleProcessingService: KClass<out SampleProcessingService> val packageListServiceClass: KClass<out PackageListService>? + val descriptorSignatureProvider: KClass<out DescriptorSignatureProvider> } diff --git a/core/src/main/kotlin/Formats/StandardFormats.kt b/core/src/main/kotlin/Formats/StandardFormats.kt index fad65ff1..f3d638c6 100644 --- a/core/src/main/kotlin/Formats/StandardFormats.kt +++ b/core/src/main/kotlin/Formats/StandardFormats.kt @@ -1,6 +1,9 @@ package org.jetbrains.dokka.Formats import org.jetbrains.dokka.* +import org.jetbrains.dokka.Kotlin.KotlinAsJavaDescriptorSignatureProvider +import org.jetbrains.dokka.Kotlin.KotlinDescriptorSignatureProvider +import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import org.jetbrains.dokka.Samples.KotlinWebsiteSampleProcessingService import org.jetbrains.dokka.Samples.SampleProcessingService @@ -14,6 +17,7 @@ abstract class KotlinFormatDescriptorBase : FormatDescriptor { override val outlineServiceClass: KClass<out OutlineFormatService>? = null override val sampleProcessingService: KClass<out SampleProcessingService> = DefaultSampleProcessingService::class override val packageListServiceClass: KClass<out PackageListService>? = DefaultPackageListService::class + override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class } class HtmlFormatDescriptor : KotlinFormatDescriptorBase() { @@ -29,6 +33,7 @@ class HtmlAsJavaFormatDescriptor : FormatDescriptor { override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class override val sampleProcessingService: KClass<out SampleProcessingService> = DefaultSampleProcessingService::class override val packageListServiceClass: KClass<out PackageListService>? = DefaultPackageListService::class + override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class } class KotlinWebsiteFormatDescriptor : KotlinFormatDescriptorBase() { diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index a8b000b7..5167a102 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -398,10 +398,29 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, else -> it.platformsToShow.toSet() } } + + fun String.isKotlinVersion() = this.startsWith("Kotlin") + // Calculating common platforms for items - return platforms.fold(platforms.first()) { - result, platforms -> - result.intersect(platforms) + return platforms.reduce { result, platformsOfItem -> + val otherKotlinVersion = result.find { it.isKotlinVersion() } + val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } + + // When no Kotlin version specified, it means that version is 1.0 + if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { + val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() + + val minVersion = allKotlinVersions.min()!! + val resultVersion = when { + allKotlinVersions.size == 1 -> allKotlinVersions.single() + minVersion.endsWith("+") -> minVersion + else -> minVersion + "+" + } + + result.intersect(otherPlatforms) + resultVersion + } else { + result.intersect(platformsOfItem) + } } } diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 17b6b156..09e5cedf 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -94,6 +94,8 @@ class DokkaGenerator(val logger: DokkaLogger, addSources(sourcePaths) addSources(this@DokkaGenerator.samples) + + loadLanguageVersionSettings(options.languageVersion, options.apiVersion) } return environment diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index f67582a7..34d4154e 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -32,26 +32,31 @@ class SourceRootImpl(path: String, override val platforms: List<String> = emptyL data class PackageOptionsImpl(override val prefix: String, override val includeNonPublic: Boolean = false, override val reportUndocumented: Boolean = true, - override val skipDeprecated: Boolean = false) : DokkaConfiguration.PackageOptions + override val skipDeprecated: Boolean = false, + override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions -data class DokkaConfigurationImpl(override val moduleName: String, - override val classpath: List<String>, - override val sourceRoots: List<SourceRootImpl>, - override val samples: List<String>, - override val includes: List<String>, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List<SourceLinkDefinitionImpl>, - override val impliedPlatforms: List<String>, - override val perPackageOptions: List<PackageOptionsImpl>, - override val externalDocumentationLinks: List<ExternalDocumentationLinkImpl>, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List<String>) : DokkaConfiguration
\ No newline at end of file +data class DokkaConfigurationImpl( + override val moduleName: String, + override val classpath: List<String>, + override val sourceRoots: List<SourceRootImpl>, + override val samples: List<String>, + override val includes: List<String>, + override val outputDir: String, + override val format: String, + override val includeNonPublic: Boolean, + override val includeRootPackage: Boolean, + override val reportUndocumented: Boolean, + override val skipEmptyPackages: Boolean, + override val skipDeprecated: Boolean, + override val jdkVersion: Int, + override val generateIndexPages: Boolean, + override val sourceLinks: List<SourceLinkDefinitionImpl>, + override val impliedPlatforms: List<String>, + override val perPackageOptions: List<PackageOptionsImpl>, + override val externalDocumentationLinks: List<ExternalDocumentationLinkImpl>, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List<String>, + override val languageVersion: String?, + override val apiVersion: String? +) : DokkaConfiguration
\ No newline at end of file diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index a950e432..cf2b0514 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtModifierListOwner +import java.io.File fun getSignature(element: PsiElement?) = when(element) { is PsiClass -> element.qualifiedName @@ -57,7 +58,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { } override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) { - if (file.classes.all { skipElement(it) }) { + if (skipFile(file) || file.classes.all { skipElement(it) }) { return } val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap(), refGraph) @@ -131,7 +132,12 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { } } - private fun skipElement(element: Any) = skipElementByVisibility(element) || hasSuppressDocTag(element) + private fun skipFile(javaFile: PsiJavaFile): Boolean = options.effectivePackageOptions(javaFile.packageName).suppress + + private fun skipElement(element: Any) = + skipElementByVisibility(element) || + hasSuppressDocTag(element) || + skipElementBySuppressedFiles(element) private fun skipElementByVisibility(element: Any): Boolean = element is PsiModifierListOwner && !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && @@ -139,6 +145,9 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || element.isInternal()) + private fun skipElementBySuppressedFiles(element: Any): Boolean = + element is PsiElement && File(element.containingFile.virtualFile.path).absoluteFile in options.suppressedFiles + private fun PsiElement.isInternal(): Boolean { val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false return (ktElement as? KtModifierListOwner)?.hasModifier(KtTokens.INTERNAL_KEYWORD) ?: false diff --git a/core/src/main/kotlin/Kotlin/ContentBuilder.kt b/core/src/main/kotlin/Kotlin/ContentBuilder.kt index 771bc44b..c60625a4 100644 --- a/core/src/main/kotlin/Kotlin/ContentBuilder.kt +++ b/core/src/main/kotlin/Kotlin/ContentBuilder.kt @@ -110,9 +110,12 @@ fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver: LinkR } MarkdownTokenTypes.CODE_LINE -> { - val block = ContentBlockCode() - block.append(ContentText(node.text)) - parent.append(block) + val content = ContentText(node.text) + if (parent is ContentBlockCode) { + parent.append(content) + } else { + parent.append(ContentBlockCode().apply { append(content) }) + } } MarkdownTokenTypes.TEXT -> { diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index 2b085769..ffef399d 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -1,16 +1,21 @@ package org.jetbrains.dokka import com.google.inject.Inject +import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi class DeclarationLinkResolver @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, val logger: DokkaLogger, val options: DocumentationOptions, - val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver) { + val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver, + val descriptorSignatureProvider: DescriptorSignatureProvider) { fun tryResolveContentLink(fromDescriptor: DeclarationDescriptor, href: String): ContentBlock? { @@ -29,7 +34,17 @@ class DeclarationLinkResolver if (externalHref != null) { return ContentExternalLink(externalHref) } - return ContentNodeLazyLink(href, { -> refGraph.lookupOrWarn(symbol.signature(), logger) }) + val signature = descriptorSignatureProvider.signature(symbol) + val referencedAt = fromDescriptor.signatureWithSourceLocation() + + return ContentNodeLazyLink(href, { -> + val target = refGraph.lookup(signature) + + if (target == null) { + logger.warn("Can't find node by signature $signature, referenced at $referencedAt") + } + target + }) } if ("/" in href) { return ContentExternalLink(href) @@ -51,6 +66,9 @@ class DeclarationLinkResolver if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { return symbol.overriddenDescriptors.firstOrNull() } + if (symbol is TypeAliasDescriptor && !symbol.isDocumented(options)) { + return symbol.classDescriptor + } return symbol } diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index eb8c12d0..f2d9d3a7 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -81,7 +81,7 @@ class DescriptorDocumentationParser val suppressAnnotation = annotations.findAnnotation(FqName(Suppress::class.qualifiedName!!)) return if (suppressAnnotation != null) { @Suppress("UNCHECKED_CAST") - (suppressAnnotation.argumentValue("names") as List<StringValue>).any { it.value == "NOT_DOCUMENTED" } + (suppressAnnotation.argumentValue("names")?.value as List<StringValue>).any { it.value == "NOT_DOCUMENTED" } } else containingDeclaration?.isSuppressWarning() ?: false } diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index fddf0814..916f89c9 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -15,14 +15,14 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.ConstantValue -import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.isDocumentedAnnotation +import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.source.PsiSourceElement @@ -50,6 +50,8 @@ class DocumentationOptions(val outputDir: String, perPackageOptions: List<PackageOptions> = emptyList(), externalDocumentationLinks: List<ExternalDocumentationLink> = emptyList(), noStdlibLink: Boolean, + val languageVersion: String?, + val apiVersion: String?, cacheRoot: String? = null, val suppressedFiles: List<File> = emptyList()) { init { @@ -576,6 +578,11 @@ class DocumentationBuilder descriptorsToDocument.mapTo(result) { ClassMember(it, inheritedLinkKind = RefKind.InheritedCompanionObjectMember) } + + if (companionObjectDescriptor.getAllSuperclassesWithoutAny().isNotEmpty() + || companionObjectDescriptor.getSuperInterfaces().isNotEmpty()) { + result += ClassMember(companionObjectDescriptor) + } } return result } @@ -726,6 +733,7 @@ class DocumentationBuilder } node.appendType(constraint, NodeKind.UpperBound) } + register(this, node) return node } @@ -746,6 +754,7 @@ class DocumentationBuilder val node = DocumentationNode(name.asString(), Content.Empty, NodeKind.Receiver) node.appendType(type) + register(this, node) return node } @@ -772,6 +781,14 @@ class DocumentationBuilder "\"" + StringUtil.escapeStringCharacters(value) + "\"" is EnumEntrySyntheticClassDescriptor -> value.containingDeclaration.name.asString() + "." + value.name.asString() + is Pair<*, *> -> { + val (classId, name) = value + if (classId is ClassId && name is Name) { + classId.shortClassName.asString() + "." + name.asString() + } else { + value.toString() + } + } else -> value.toString() }.let { valueString -> DocumentationNode(valueString, Content.Empty, NodeKind.Value) @@ -784,9 +801,9 @@ val visibleToDocumentation = setOf(Visibilities.PROTECTED, Visibilities.PUBLIC) fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean { return (options.effectivePackageOptions(fqNameSafe).includeNonPublic || this !is MemberDescriptor - || this.visibility in visibleToDocumentation) && - !isDocumentationSuppressed(options) && - (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) + || this.visibility in visibleToDocumentation) + && !isDocumentationSuppressed(options) + && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) } private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION @@ -856,6 +873,8 @@ fun AnnotationDescriptor.mustBeDocumented(): Boolean { fun DeclarationDescriptor.isDocumentationSuppressed(options: DocumentationOptions): Boolean { + if (options.effectivePackageOptions(fqNameSafe).suppress) return true + val path = this.findPsi()?.containingFile?.virtualFile?.path if (path != null) { if (File(path).absoluteFile in options.suppressedFiles) return true @@ -905,17 +924,21 @@ fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor return null } -fun DeclarationDescriptor.signature(): String = when (this) { - is ClassDescriptor, - is PackageFragmentDescriptor, - is PackageViewDescriptor, - is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() - - is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() - is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name - is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name - else -> throw UnsupportedOperationException("Don't know how to calculate signature for $this") +fun DeclarationDescriptor.signature(): String { + if (this != original) return original.signature() + return when (this) { + is ClassDescriptor, + is PackageFragmentDescriptor, + is PackageViewDescriptor, + is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() + + is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name + is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name + is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name + else -> throw UnsupportedOperationException("Don't know how to calculate signature for $this") + } } fun PropertyDescriptor.receiverSignature(): String { @@ -932,7 +955,7 @@ fun CallableMemberDescriptor.parameterSignature(): String { if (extensionReceiver != null) { params.add(0, extensionReceiver.type) } - return "(" + params.map { it.signature() }.joinToString() + ")" + return params.joinToString(prefix = "(", postfix = ")") { it.signature() } } fun KotlinType.signature(): String { diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 84d83c73..108cee78 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -15,7 +15,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.parents import java.io.ByteArrayOutputStream import java.io.PrintWriter +import java.net.HttpURLConnection import java.net.URL +import java.net.URLConnection import java.nio.file.Path import java.security.MessageDigest @@ -30,12 +32,44 @@ class ExternalDocumentationLinkResolver @Inject constructor( val packageFqNameToLocation = mutableMapOf<FqName, ExternalDocumentationRoot>() val formats = mutableMapOf<String, InboundExternalLinkResolutionService>() - class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map<String, String>) + class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map<String, String>) { + override fun toString(): String = rootUrl.toString() + } val cacheDir: Path? = options.cacheRoot?.resolve("packageListCache")?.apply { createDirectories() } val cachedProtocols = setOf("http", "https", "ftp") + fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection { + val connection = this.openConnection() + connection.connectTimeout = timeout + connection.readTimeout = timeout + + when (connection) { + is HttpURLConnection -> { + return when (connection.responseCode) { + in 200..299 -> { + connection + } + HttpURLConnection.HTTP_MOVED_PERM, + HttpURLConnection.HTTP_MOVED_TEMP, + HttpURLConnection.HTTP_SEE_OTHER -> { + if (redirectsAllowed > 0) { + val newUrl = connection.getHeaderField("Location") + URL(newUrl).doOpenConnectionToReadContent(timeout, redirectsAllowed - 1) + } else { + throw RuntimeException("Too many redirects") + } + } + else -> { + throw RuntimeException("Unhandled http code: ${connection.responseCode}") + } + } + } + else -> return connection + } + } + fun loadPackageList(link: DokkaConfiguration.ExternalDocumentationLink) { val packageListUrl = link.packageListUrl @@ -50,7 +84,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( if (cacheEntry.exists()) { try { - val connection = packageListUrl.openConnection() + val connection = packageListUrl.doOpenConnectionToReadContent() val originModifiedDate = connection.date val cacheDate = cacheEntry.lastModified().toMillis() if (originModifiedDate > cacheDate || originModifiedDate == 0L) { @@ -60,7 +94,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( logger.info("Renewing package-list from $packageListUrl") connection.getInputStream().copyTo(cacheEntry.outputStream()) } - } catch(e: Exception) { + } catch (e: Exception) { logger.error("Failed to update package-list cache for $link") val baos = ByteArrayOutputStream() PrintWriter(baos).use { @@ -75,7 +109,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( } cacheEntry.inputStream() } else { - packageListUrl.openStream() + packageListUrl.doOpenConnectionToReadContent().getInputStream() } val (params, packages) = diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt new file mode 100644 index 00000000..a3be658e --- /dev/null +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt @@ -0,0 +1,22 @@ +package org.jetbrains.dokka.Kotlin + +import org.jetbrains.dokka.Model.DescriptorSignatureProvider +import org.jetbrains.dokka.getSignature +import org.jetbrains.dokka.sourcePsi +import org.jetbrains.kotlin.asJava.toLightElements +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.KtElement + +class KotlinAsJavaDescriptorSignatureProvider : DescriptorSignatureProvider { + override fun signature(forDesc: DeclarationDescriptor): String { + val sourcePsi = forDesc.sourcePsi() + val javaLikePsi = if (sourcePsi is KtElement) { + sourcePsi.toLightElements().firstOrNull() + } else { + sourcePsi + } + + return getSignature(javaLikePsi) ?: + "not implemented for $forDesc with psi: $sourcePsi" + } +}
\ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt new file mode 100644 index 00000000..7ecd0389 --- /dev/null +++ b/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt @@ -0,0 +1,9 @@ +package org.jetbrains.dokka.Kotlin + +import org.jetbrains.dokka.Model.DescriptorSignatureProvider +import org.jetbrains.dokka.signature +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +class KotlinDescriptorSignatureProvider : DescriptorSignatureProvider { + override fun signature(forDesc: DeclarationDescriptor): String = forDesc.signature() +}
\ No newline at end of file diff --git a/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt b/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt new file mode 100644 index 00000000..85584e3c --- /dev/null +++ b/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt @@ -0,0 +1,7 @@ +package org.jetbrains.dokka.Model + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +interface DescriptorSignatureProvider { + fun signature(forDesc: DeclarationDescriptor): String +}
\ No newline at end of file diff --git a/core/src/main/kotlin/Model/PackageDocs.kt b/core/src/main/kotlin/Model/PackageDocs.kt index 3b03324c..1f6bdcb9 100644 --- a/core/src/main/kotlin/Model/PackageDocs.kt +++ b/core/src/main/kotlin/Model/PackageDocs.kt @@ -32,7 +32,7 @@ class PackageDocs targetContent = findTargetContent(headingText.trimStart()) } } else { - buildContentTo(it, targetContent, LinkResolver(linkMap, { resolveContentLink(it, linkResolveContext) })) + buildContentTo(it, targetContent, LinkResolver(linkMap, { resolveContentLink(fileName, it, linkResolveContext) })) } } } else { @@ -53,7 +53,7 @@ class PackageDocs private fun findOrCreatePackageContent(packageName: String) = _packageContent.getOrPut(packageName) { -> MutableContent() } - private fun resolveContentLink(href: String, linkResolveContext: List<PackageFragmentDescriptor>): ContentBlock { + private fun resolveContentLink(fileName: String, href: String, linkResolveContext: List<PackageFragmentDescriptor>): ContentBlock { if (linkResolver != null) { linkResolveContext .asSequence() @@ -62,6 +62,7 @@ class PackageDocs .firstOrNull() ?.let { return it } } + logger.warn("Unresolved link to `$href` in include ($fileName)") return ContentExternalLink("#") } }
\ No newline at end of file diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index 4dd0bc7f..b0988c35 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -2,11 +2,13 @@ package org.jetbrains.dokka.Samples import com.google.inject.Inject import com.intellij.psi.PsiElement +import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.dokka.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.allChildren +import org.jetbrains.kotlin.psi.psiUtil.prevLeaf import org.jetbrains.kotlin.resolve.ImportPath open class KotlinWebsiteSampleProcessingService @@ -35,14 +37,19 @@ open class KotlinWebsiteSampleProcessingService } } - fun convertAssertTrue(expression: KtCallExpression) { + fun convertAssertTrueFalse(expression: KtCallExpression, expectedResult: Boolean) { val (argument) = expression.valueArguments builder.apply { + expression.valueArguments.getOrNull(1)?.let { + append("// ${it.extractStringArgumentValue()}") + val ws = expression.prevLeaf { it is PsiWhiteSpace } + append(ws?.text ?: "\n") + } append("println(\"") append(argument.text) append(" is \${") append(argument.text) - append("}\") // true") + append("}\") // $expectedResult") } } @@ -77,7 +84,8 @@ open class KotlinWebsiteSampleProcessingService override fun visitCallExpression(expression: KtCallExpression) { when (expression.calleeExpression?.text) { "assertPrints" -> convertAssertPrints(expression) - "assertTrue" -> convertAssertTrue(expression) + "assertTrue" -> convertAssertTrueFalse(expression, expectedResult = true) + "assertFalse" -> convertAssertTrueFalse(expression, expectedResult = false) "assertFails" -> convertAssertFails(expression) "assertFailsWith" -> convertAssertFailsWith(expression) else -> super.visitCallExpression(expression) diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 28c5dc45..dfb114ec 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -7,6 +7,7 @@ import com.google.inject.TypeLiteral import com.google.inject.name.Names import org.jetbrains.dokka.* import org.jetbrains.dokka.Formats.FormatDescriptor +import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.dokka.Samples.SampleProcessingService import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import java.io.File @@ -22,7 +23,7 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind<DokkaLogger>().toInstance(logger) val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", options.outputFormat) - + binder.bind<DescriptorSignatureProvider>().to(descriptor.descriptorSignatureProvider.java) binder.registerCategory<LanguageService>("language") binder.bind<PackageDocumentationBuilder>().to(descriptor.packageDocumentationBuilderClass.java) binder.bind<JavaDocumentationBuilder>().to(descriptor.javaDocumentationBuilderClass.java) diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt index 9555aeb9..c98a3801 100644 --- a/core/src/main/kotlin/javadoc/dokka-adapters.kt +++ b/core/src/main/kotlin/javadoc/dokka-adapters.kt @@ -4,6 +4,8 @@ import com.google.inject.Inject import com.sun.tools.doclets.formats.html.HtmlDoclet import org.jetbrains.dokka.* import org.jetbrains.dokka.Formats.FormatDescriptor +import org.jetbrains.dokka.Kotlin.KotlinAsJavaDescriptorSignatureProvider +import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import kotlin.reflect.KClass @@ -36,4 +38,5 @@ class JavadocFormatDescriptor : FormatDescriptor { override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class override val packageListServiceClass: KClass<out PackageListService>? = null + override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class } diff --git a/core/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java b/core/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java deleted file mode 100644 index cbb1cc3c..00000000 --- a/core/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java +++ /dev/null @@ -1,39 +0,0 @@ - -package com.intellij.rt.execution.junit; - -import junit.framework.ComparisonFailure; - -public class FileComparisonFailure extends ComparisonFailure implements KnownException { - private final String myExpected; - private final String myActual; - private final String myFilePath; - private final String myActualFilePath; - - public FileComparisonFailure(String message, String expected, String actual, String filePath) { - this(message, expected, actual, filePath, (String)null); - } - - public FileComparisonFailure(String message, String expected, String actual, String expectedFilePath, String actualFilePath) { - super(message, expected, actual); - this.myExpected = expected; - this.myActual = actual; - this.myFilePath = expectedFilePath; - this.myActualFilePath = actualFilePath; - } - - public String getFilePath() { - return this.myFilePath; - } - - public String getActualFilePath() { - return this.myActualFilePath; - } - - public String getExpected() { - return this.myExpected; - } - - public String getActual() { - return this.myActual; - } -} diff --git a/core/src/test/java/com/intellij/rt/execution/junit/KnownException.java b/core/src/test/java/com/intellij/rt/execution/junit/KnownException.java deleted file mode 100644 index c24653ea..00000000 --- a/core/src/test/java/com/intellij/rt/execution/junit/KnownException.java +++ /dev/null @@ -1,6 +0,0 @@ - -package com.intellij.rt.execution.junit; - -interface KnownException { - -} diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index a1a98ec7..ff8a5260 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -24,17 +24,24 @@ fun verifyModel(vararg roots: ContentRoot, withKotlinRuntime: Boolean = false, format: String = "html", includeNonPublic: Boolean = true, + perPackageOptions: List<DokkaConfiguration.PackageOptions> = emptyList(), verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") - val options = DocumentationOptions("", format, + val options = DocumentationOptions( + "", + format, includeNonPublic = includeNonPublic, skipEmptyPackages = false, includeRootPackage = true, - sourceLinks = listOf<SourceLinkDefinition>(), + sourceLinks = listOf(), + perPackageOptions = perPackageOptions, generateIndexPages = false, noStdlibLink = true, - cacheRoot = "default") + cacheRoot = "default", + languageVersion = null, + apiVersion = null + ) appendDocumentation(documentation, *roots, withJdk = withJdk, @@ -86,6 +93,8 @@ fun appendDocumentation(documentation: DocumentationModule, addClasspath(File(kotlinStrictfpRoot)) } addRoots(roots.toList()) + + loadLanguageVersionSettings(options.languageVersion, options.apiVersion) } val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = defaultPlatforms @@ -151,8 +160,15 @@ fun verifyOutput(roots: Array<ContentRoot>, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, format: String = "html", + includeNonPublic: Boolean = true, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { - verifyModel(*roots, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime, format = format) { + verifyModel( + *roots, + withJdk = withJdk, + withKotlinRuntime = withKotlinRuntime, + format = format, + includeNonPublic = includeNonPublic + ) { verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator) } } @@ -173,8 +189,17 @@ fun verifyOutput(path: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, format: String = "html", + includeNonPublic: Boolean = true, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { - verifyOutput(arrayOf(contentRootFromPath(path)), outputExtension, withJdk, withKotlinRuntime, format, outputGenerator) + verifyOutput( + arrayOf(contentRootFromPath(path)), + outputExtension, + withJdk, + withKotlinRuntime, + format, + includeNonPublic, + outputGenerator + ) } fun verifyJavaOutput(path: String, diff --git a/core/src/test/kotlin/format/HtmlFormatTest.kt b/core/src/test/kotlin/format/HtmlFormatTest.kt index 4fe4f6ab..01e4559e 100644 --- a/core/src/test/kotlin/format/HtmlFormatTest.kt +++ b/core/src/test/kotlin/format/HtmlFormatTest.kt @@ -146,6 +146,10 @@ class HtmlFormatTest { verifyHtmlNode("blankLineInsideCodeBlock") } + @Test fun indentedCodeBlock() { + verifyHtmlNode("indentedCodeBlock") + } + private fun verifyHtmlNode(fileName: String, withKotlinRuntime: Boolean = false) { verifyHtmlNodes(fileName, withKotlinRuntime) { model -> model.members.single().members } } diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt index f4ca2982..af44b048 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt @@ -42,7 +42,14 @@ class KotlinWebSiteFormatTest { private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions("", "html", generateIndexPages = false, noStdlibLink = true) + val options = DocumentationOptions( + outputDir = "", + outputFormat = "html", + generateIndexPages = false, + noStdlibLink = true, + languageVersion = null, + apiVersion = null + ) appendDocumentation(module, contentRootFromPath("testdata/format/website/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options) appendDocumentation(module, contentRootFromPath("testdata/format/website/$path/jre7.kt"), defaultPlatforms = listOf("JVM", "JRE7"), options = options) appendDocumentation(module, contentRootFromPath("testdata/format/website/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options) diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index b4b133f4..433c9c13 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -57,7 +57,14 @@ class KotlinWebSiteHtmlFormatTest { private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions("", "html", generateIndexPages = false, noStdlibLink = true) + val options = DocumentationOptions( + outputDir = "", + outputFormat = "kotlin-website-html", + generateIndexPages = false, + noStdlibLink = true, + languageVersion = null, + apiVersion = null + ) appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options) appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/jre7.kt"), defaultPlatforms = listOf("JVM", "JRE7"), options = options) appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options) diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 48b06d6e..820af361 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -251,6 +251,10 @@ class MarkdownFormatTest { verifyMarkdownPackage("sinceKotlin") } + @Test fun sinceKotlinWide() { + verifyMarkdownPackage("sinceKotlinWide") + } + @Test fun dynamicType() { verifyMarkdownNode("dynamicType") } @@ -300,7 +304,14 @@ class MarkdownFormatTest { @Test fun packagePlatformsWithExtExtensions() { val path = "multiplatform/packagePlatformsWithExtExtensions" val module = DocumentationModule("test") - val options = DocumentationOptions("", "html", generateIndexPages = false, noStdlibLink = true) + val options = DocumentationOptions( + outputDir = "", + outputFormat = "html", + generateIndexPages = false, + noStdlibLink = true, + languageVersion = null, + apiVersion = null + ) appendDocumentation(module, contentRootFromPath("testdata/format/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), withKotlinRuntime = true, options = options) verifyMultiplatformIndex(module, path) verifyMultiplatformPackage(module, path) @@ -376,9 +387,40 @@ class MarkdownFormatTest { verifyMarkdownPackage("newlineInTableCell") } + @Test fun indentedCodeBlock() { + verifyMarkdownNode("indentedCodeBlock") + } + + @Test fun receiverReference() { + verifyMarkdownNode("receiverReference") + } + + @Test fun extensionScope() { + verifyMarkdownNodeByName("extensionScope", "test") + } + + @Test fun typeParameterReference() { + verifyMarkdownNode("typeParameterReference") + } + + @Test fun notPublishedTypeAliasAutoExpansion() { + verifyMarkdownNodeByName("notPublishedTypeAliasAutoExpansion", "foo", includeNonPublic = false) + } + + @Test fun companionImplements() { + verifyMarkdownNodeByName("companionImplements", "Foo") + } + private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions("", "html", generateIndexPages = false, noStdlibLink = true) + val options = DocumentationOptions( + outputDir = "", + outputFormat = "html", + generateIndexPages = false, + noStdlibLink = true, + languageVersion = null, + apiVersion = null + ) appendDocumentation(module, contentRootFromPath("testdata/format/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options) appendDocumentation(module, contentRootFromPath("testdata/format/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options) return module @@ -412,8 +454,18 @@ class MarkdownFormatTest { verifyMarkdownNodes(fileName, withKotlinRuntime) { model -> model.members.single().members } } - private fun verifyMarkdownNodes(fileName: String, withKotlinRuntime: Boolean = false, nodeFilter: (DocumentationModule) -> List<DocumentationNode>) { - verifyOutput("testdata/format/$fileName.kt", ".md", withKotlinRuntime = withKotlinRuntime) { model, output -> + private fun verifyMarkdownNodes( + fileName: String, + withKotlinRuntime: Boolean = false, + includeNonPublic: Boolean = true, + nodeFilter: (DocumentationModule) -> List<DocumentationNode> + ) { + verifyOutput( + "testdata/format/$fileName.kt", + ".md", + withKotlinRuntime = withKotlinRuntime, + includeNonPublic = includeNonPublic + ) { model, output -> markdownService.createOutputBuilder(output, tempLocation).appendNodes(nodeFilter(model)) } } @@ -428,8 +480,13 @@ class MarkdownFormatTest { } } - private fun verifyMarkdownNodeByName(fileName: String, name: String, withKotlinRuntime: Boolean = false) { - verifyMarkdownNodes(fileName, withKotlinRuntime) { model-> + private fun verifyMarkdownNodeByName( + fileName: String, + name: String, + withKotlinRuntime: Boolean = false, + includeNonPublic: Boolean = true + ) { + verifyMarkdownNodes(fileName, withKotlinRuntime, includeNonPublic) { model-> val nodesWithName = model.members.single().members.filter { it.name == name } if (nodesWithName.isEmpty()) { throw IllegalArgumentException("Found no nodes named $name") diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 359c5fef..45c45aa4 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -151,6 +151,16 @@ class JavadocTest { } } + @Test + fun testCompanionMethodReference() { + verifyJavadoc("testdata/javadoc/companionMethodReference.kt") { doc -> + val classDoc = doc.classNamed("foo.TestClass")!! + val tag = classDoc.inlineTags().filterIsInstance<SeeMethodTagAdapter>().first() + assertEquals("TestClass.Companion", tag.referencedClassName()) + assertEquals("test", tag.referencedMemberName()) + } + } + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/src/test/kotlin/model/FunctionTest.kt b/core/src/test/kotlin/model/FunctionTest.kt index 065decef..32910682 100644 --- a/core/src/test/kotlin/model/FunctionTest.kt +++ b/core/src/test/kotlin/model/FunctionTest.kt @@ -5,6 +5,7 @@ import org.jetbrains.dokka.NodeKind import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test +import kotlin.test.assertNotNull class FunctionTest { @Test fun function() { @@ -83,9 +84,10 @@ class FunctionTest { assertEquals(NodeKind.Function, kind) assertEquals("generic function", content.summary.toTestString()) - assertEquals("public", details.elementAt(0).name) - assertEquals("final", details.elementAt(1).name) - with(details.elementAt(3)) { + val functionDetails = details + assertEquals("public", functionDetails.elementAt(0).name) + assertEquals("final", functionDetails.elementAt(1).name) + with(functionDetails.elementAt(3)) { assertEquals("T", name) assertEquals(NodeKind.TypeParameter, kind) assertEquals(Content.Empty, content) @@ -95,19 +97,19 @@ class FunctionTest { assertEquals(Content.Empty, content) assertTrue(details.none()) assertTrue(members.none()) - assertTrue(links.none()) + assertTrue(links.singleOrNull() == functionDetails.elementAt(4)) } assertTrue(members.none()) assertTrue(links.none()) } - with(details.elementAt(4)) { + with(functionDetails.elementAt(4)) { assertEquals("R", name) assertEquals(NodeKind.TypeParameter, kind) assertEquals(Content.Empty, content) assertTrue(members.none()) assertTrue(links.none()) } - assertEquals("Unit", details.elementAt(5).name) + assertEquals("Unit", functionDetails.elementAt(5).name) assertTrue(members.none()) assertTrue(links.none()) diff --git a/core/src/test/kotlin/model/PackageTest.kt b/core/src/test/kotlin/model/PackageTest.kt index 97810e80..052f0d28 100644 --- a/core/src/test/kotlin/model/PackageTest.kt +++ b/core/src/test/kotlin/model/PackageTest.kt @@ -2,10 +2,10 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.Content import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.PackageOptionsImpl import org.jetbrains.kotlin.config.KotlinSourceRoot +import org.junit.Assert.* import org.junit.Test -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue public class PackageTest { @Test fun rootPackage() { @@ -83,4 +83,33 @@ public class PackageTest { } } } -}
\ No newline at end of file + + @Test fun classAtPackageLevel() { + verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt")) { model -> + assertEquals(1, model.members.count()) + with(model.members.elementAt(0)) { + assertEquals(NodeKind.Package, kind) + assertEquals("simple.name", name) + assertEquals(Content.Empty, content) + assertTrue(details.none()) + assertEquals(1, members.size) + assertTrue(links.none()) + } + } + } + + @Test fun suppressAtPackageLevel() { + verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt"), + perPackageOptions = listOf(PackageOptionsImpl(prefix = "simple.name", suppress = true))) { model -> + assertEquals(1, model.members.count()) + with(model.members.elementAt(0)) { + assertEquals(NodeKind.Package, kind) + assertEquals("simple.name", name) + assertEquals(Content.Empty, content) + assertTrue(details.none()) + assertTrue(members.none()) + assertTrue(links.none()) + } + } + } +} diff --git a/core/testdata/format/annotatedTypeParameter.md b/core/testdata/format/annotatedTypeParameter.md index 0aa1b9d7..aa8b8592 100644 --- a/core/testdata/format/annotatedTypeParameter.md +++ b/core/testdata/format/annotatedTypeParameter.md @@ -2,4 +2,4 @@ # containsAll -`fun <E> containsAll(elements: Collection<@UnsafeVariance E>): @UnsafeVariance E`
\ No newline at end of file +`fun <E> containsAll(elements: Collection<@UnsafeVariance `[`E`](test/contains-all#E)`>): @UnsafeVariance `[`E`](test/contains-all#E)
\ No newline at end of file diff --git a/core/testdata/format/companionImplements.kt b/core/testdata/format/companionImplements.kt new file mode 100644 index 00000000..154ef9b1 --- /dev/null +++ b/core/testdata/format/companionImplements.kt @@ -0,0 +1,9 @@ + +interface Bar + +/** + * Correct ref [Foo.Companion] + */ +class Foo { + companion object : Bar +}
\ No newline at end of file diff --git a/core/testdata/format/companionImplements.md b/core/testdata/format/companionImplements.md new file mode 100644 index 00000000..8a93ed6b --- /dev/null +++ b/core/testdata/format/companionImplements.md @@ -0,0 +1,16 @@ +[test](test/index) / [Foo](test/-foo/index) + +# Foo + +`class Foo` + +Correct ref [Foo.Companion](test/-foo/-companion) + +### Types + +| [Companion](test/-foo/-companion) | `companion object Companion : `[`Bar`](test/-bar) | + +### Constructors + +| [<init>](test/-foo/-init-) | `Foo()`<br>Correct ref [Foo.Companion](test/-foo/-companion) | + diff --git a/core/testdata/format/extensionFunctionParameter.md b/core/testdata/format/extensionFunctionParameter.md index b459d49e..501d731d 100644 --- a/core/testdata/format/extensionFunctionParameter.md +++ b/core/testdata/format/extensionFunctionParameter.md @@ -2,4 +2,4 @@ # apply -`inline fun <T> T.apply(f: T.() -> Unit): T`
\ No newline at end of file +`inline fun <T> `[`T`](test/apply#T)`.apply(f: `[`T`](test/apply#T)`.() -> Unit): `[`T`](test/apply#T)
\ No newline at end of file diff --git a/core/testdata/format/extensionScope.kt b/core/testdata/format/extensionScope.kt new file mode 100644 index 00000000..9f3130b8 --- /dev/null +++ b/core/testdata/format/extensionScope.kt @@ -0,0 +1,14 @@ +/** + * Test class with Type-parameter + */ +class Foo<T> + +/** + * Some extension on Foo + */ +fun <T> Foo<T>.ext() {} + +/** + * Correct link: [Foo.ext] + */ +fun test() {}
\ No newline at end of file diff --git a/core/testdata/format/extensionScope.md b/core/testdata/format/extensionScope.md new file mode 100644 index 00000000..3515ed84 --- /dev/null +++ b/core/testdata/format/extensionScope.md @@ -0,0 +1,8 @@ +[test](test/index) / [test](test/test) + +# test + +`fun test(): Unit` + +Correct link: [Foo.ext](test/ext) + diff --git a/core/testdata/format/genericInheritedExtensions.md b/core/testdata/format/genericInheritedExtensions.md index a3091aeb..163ff0c9 100644 --- a/core/testdata/format/genericInheritedExtensions.md +++ b/core/testdata/format/genericInheritedExtensions.md @@ -2,7 +2,7 @@ # Bar -`class Bar<T> : `[`Foo`](test/-foo/index)`<T>` +`class Bar<T> : `[`Foo`](test/-foo/index)`<`[`T`](test/-bar/index#T)`>` ### Constructors @@ -10,6 +10,6 @@ ### Extension Functions -| [first](test/first) | `fun <T> `[`Foo`](test/-foo/index)`<T>.first(): Unit` | -| [second](test/second) | `fun <T> `[`Bar`](test/-bar/index)`<T>.second(): Unit` | +| [first](test/first) | `fun <T> `[`Foo`](test/-foo/index)`<`[`T`](test/first#T)`>.first(): Unit` | +| [second](test/second) | `fun <T> `[`Bar`](test/-bar/index)`<`[`T`](test/second#T)`>.second(): Unit` | diff --git a/core/testdata/format/htmlEscaping.html b/core/testdata/format/htmlEscaping.html index fd9a3235..17d48161 100644 --- a/core/testdata/format/htmlEscaping.html +++ b/core/testdata/format/htmlEscaping.html @@ -8,7 +8,7 @@ <br/> <h1>x</h1> <a name="$x()"></a> -<code><span class="keyword">fun </span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span> <span class="identifier">x</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">T</span><span class="symbol">?</span></code> +<code><span class="keyword">fun </span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span> <span class="identifier">x</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><a href="test/x#T"><span class="identifier">T</span></a><span class="symbol">?</span></code> <p>Special characters: < is "less than", > is "greater than", & is "ampersand"</p> </BODY> </HTML> diff --git a/core/testdata/format/indentedCodeBlock.html b/core/testdata/format/indentedCodeBlock.html new file mode 100644 index 00000000..1ccf800a --- /dev/null +++ b/core/testdata/format/indentedCodeBlock.html @@ -0,0 +1,17 @@ +<HTML> +<HEAD> +<meta charset="UTF-8"> +<title>foo - test</title> +</HEAD> +<BODY> +<a href="test/index">test</a> / <a href="test/foo">foo</a><br/> +<br/> +<h1>foo</h1> +<a name="$foo()"></a> +<code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code> +<p>Create a new Foo value as follows:</p> +<pre><code> val foo = Foo.create { + type { "ABC" } + }</code></pre> +</BODY> +</HTML> diff --git a/core/testdata/format/indentedCodeBlock.kt b/core/testdata/format/indentedCodeBlock.kt new file mode 100644 index 00000000..19c5365b --- /dev/null +++ b/core/testdata/format/indentedCodeBlock.kt @@ -0,0 +1,10 @@ +/** + * Create a new Foo value as follows: + * + * val foo = Foo.create { + * type { "ABC" } + * } + */ +fun foo() { + +}
\ No newline at end of file diff --git a/core/testdata/format/indentedCodeBlock.md b/core/testdata/format/indentedCodeBlock.md new file mode 100644 index 00000000..515bfee3 --- /dev/null +++ b/core/testdata/format/indentedCodeBlock.md @@ -0,0 +1,14 @@ +[test](test/index) / [foo](test/foo) + +# foo + +`fun foo(): Unit` + +Create a new Foo value as follows: + +``` + val foo = Foo.create { + type { "ABC" } + } +``` + diff --git a/core/testdata/format/inheritedCompanionObjectProperties.md b/core/testdata/format/inheritedCompanionObjectProperties.md index b3b3230e..db764ff0 100644 --- a/core/testdata/format/inheritedCompanionObjectProperties.md +++ b/core/testdata/format/inheritedCompanionObjectProperties.md @@ -4,6 +4,10 @@ `class C : `[`A`](test/-a/index) +### Types + +| [Companion](test/-c/-companion/index) | `companion object Companion : `[`B`](test/-b/index) | + ### Constructors | [<init>](test/-c/-init-) | `C()` | diff --git a/core/testdata/format/notPublishedTypeAliasAutoExpansion.kt b/core/testdata/format/notPublishedTypeAliasAutoExpansion.kt new file mode 100644 index 00000000..1f29e110 --- /dev/null +++ b/core/testdata/format/notPublishedTypeAliasAutoExpansion.kt @@ -0,0 +1,13 @@ + +class A +class B + + +internal typealias TA = A +private typealias TB = B + +/** + * Correct ref [TA] + * Correct ref [TB] + */ +fun foo() {}
\ No newline at end of file diff --git a/core/testdata/format/notPublishedTypeAliasAutoExpansion.md b/core/testdata/format/notPublishedTypeAliasAutoExpansion.md new file mode 100644 index 00000000..9e0f1560 --- /dev/null +++ b/core/testdata/format/notPublishedTypeAliasAutoExpansion.md @@ -0,0 +1,9 @@ +[test](test/index) / [foo](test/foo) + +# foo + +`fun foo(): Unit` + +Correct ref [TA](test/-a/index) +Correct ref [TB](test/-b/index) + diff --git a/core/testdata/format/nullability.md b/core/testdata/format/nullability.md index 6a4c3761..014eb485 100644 --- a/core/testdata/format/nullability.md +++ b/core/testdata/format/nullability.md @@ -10,5 +10,5 @@ ### Functions -| [foo](test/-c/foo) | `fun foo(): Comparable<T>?` | +| [foo](test/-c/foo) | `fun foo(): Comparable<`[`T`](test/-c/index#T)`>?` | diff --git a/core/testdata/format/parameterAnchor.html b/core/testdata/format/parameterAnchor.html index ecb89fe6..3ffcf595 100644 --- a/core/testdata/format/parameterAnchor.html +++ b/core/testdata/format/parameterAnchor.html @@ -8,7 +8,7 @@ <br/> <h1>processFiles</h1> <a name="$processFiles(kotlin.Function0((processFiles.T)))"></a> -<code><span class="keyword">fun </span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span> <span class="identifier">processFiles</span><span class="symbol">(</span><span class="identifier" id="$processFiles(kotlin.Function0((processFiles.T)))/processor">processor</span><span class="symbol">:</span> <span class="symbol">(</span><span class="symbol">)</span> <span class="symbol">-></span> <span class="identifier">T</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">List</span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span></code> +<code><span class="keyword">fun </span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span> <span class="identifier">processFiles</span><span class="symbol">(</span><span class="identifier" id="$processFiles(kotlin.Function0((processFiles.T)))/processor">processor</span><span class="symbol">:</span> <span class="symbol">(</span><span class="symbol">)</span> <span class="symbol">-></span> <a href="test/process-files#T"><span class="identifier">T</span></a><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">List</span><span class="symbol"><</span><a href="test/process-files#T"><span class="identifier">T</span></a><span class="symbol">></span></code> <p>Runs <a href="test/process-files#$processFiles(kotlin.Function0((processFiles.T)))/processor">processor</a> for each file and collects its results into single list</p> <h3>Parameters</h3> <p><a name="processor"></a> diff --git a/core/testdata/format/receiverParameterTypeBound.md b/core/testdata/format/receiverParameterTypeBound.md index 8a8c4220..9c767449 100644 --- a/core/testdata/format/receiverParameterTypeBound.md +++ b/core/testdata/format/receiverParameterTypeBound.md @@ -10,5 +10,5 @@ ### Extension Functions -| [xyzzy](test/xyzzy) | `fun <T : `[`Foo`](test/-foo/index)`> T.xyzzy(): Unit` | +| [xyzzy](test/xyzzy) | `fun <T : `[`Foo`](test/-foo/index)`> `[`T`](test/xyzzy#T)`.xyzzy(): Unit` | diff --git a/core/testdata/format/receiverReference.kt b/core/testdata/format/receiverReference.kt new file mode 100644 index 00000000..3e6e2056 --- /dev/null +++ b/core/testdata/format/receiverReference.kt @@ -0,0 +1,6 @@ +/** + * Prints [this] + */ +fun String.some() { + println(this) +}
\ No newline at end of file diff --git a/core/testdata/format/receiverReference.md b/core/testdata/format/receiverReference.md new file mode 100644 index 00000000..1584b2b1 --- /dev/null +++ b/core/testdata/format/receiverReference.md @@ -0,0 +1,6 @@ +[test](test/index) / [kotlin.String](test/kotlin.-string/index) + +### Extensions for kotlin.String + +| [some](test/kotlin.-string/some) | `fun String.some(): Unit`<br>Prints [this](test/kotlin.-string/some/-this-) | + diff --git a/core/testdata/format/sinceKotlinWide.kt b/core/testdata/format/sinceKotlinWide.kt new file mode 100644 index 00000000..fa1eb7de --- /dev/null +++ b/core/testdata/format/sinceKotlinWide.kt @@ -0,0 +1,11 @@ +/** + * Useful + */ +@SinceKotlin("1.1") +class `Since1.1` + +/** + * Useful also + */ +@SinceKotlin("1.2") +class `Since1.2`
\ No newline at end of file diff --git a/core/testdata/format/sinceKotlinWide.package.md b/core/testdata/format/sinceKotlinWide.package.md new file mode 100644 index 00000000..f683b178 --- /dev/null +++ b/core/testdata/format/sinceKotlinWide.package.md @@ -0,0 +1,11 @@ +[test](test/index) + +## Package <root> + +**Platform and version requirements:** Kotlin 1.1+ + +### Types + +| [Since1.1](test/-since1.1/index)<br>(Kotlin 1.1) | `class Since1.1`<br>Useful | +| [Since1.2](test/-since1.2/index)<br>(Kotlin 1.2) | `class Since1.2`<br>Useful also | + diff --git a/core/testdata/format/summarizeSignatures.md b/core/testdata/format/summarizeSignatures.md index d37f2301..c1830fb5 100644 --- a/core/testdata/format/summarizeSignatures.md +++ b/core/testdata/format/summarizeSignatures.md @@ -10,5 +10,5 @@ ### Functions -| [foo](test/kotlin/foo) | `fun <T> any_array<T>.foo(predicate: (T) -> Boolean): Boolean`<br>Returns true if foo. | +| [foo](test/kotlin/foo) | `fun <T> any_array<T>.foo(predicate: (`[`T`](test/kotlin/foo#T)`) -> Boolean): Boolean`<br>Returns true if foo. | diff --git a/core/testdata/format/typeAliases.md b/core/testdata/format/typeAliases.md index 55e9317e..2a813c32 100644 --- a/core/testdata/format/typeAliases.md +++ b/core/testdata/format/typeAliases.md @@ -30,11 +30,11 @@ # H -`typealias H<T> = `[`C`](test/-c/index)`<T>`[test](test/index) / [I](test/-i) +`typealias H<T> = `[`C`](test/-c/index)`<`[`T`](test/-h#T)`>`[test](test/index) / [I](test/-i) # I -`typealias I<T> = `[`H`](test/-h)`<T>`[test](test/index) / [J](test/-j) +`typealias I<T> = `[`H`](test/-h)`<`[`T`](test/-i#T)`>`[test](test/index) / [J](test/-j) # J diff --git a/core/testdata/format/typeAliases.package.md b/core/testdata/format/typeAliases.package.md index 0eff1ed5..9407588b 100644 --- a/core/testdata/format/typeAliases.package.md +++ b/core/testdata/format/typeAliases.package.md @@ -14,8 +14,8 @@ | [E](test/-e) | `typealias E = `[`D`](test/-d) | | [F](test/-f) | `typealias F = (`[`A`](test/-a/index)`) -> `[`B`](test/-b/index) | | [G](test/-g) | `typealias G = `[`C`](test/-c/index)`<`[`A`](test/-a/index)`>` | -| [H](test/-h) | `typealias H<T> = `[`C`](test/-c/index)`<T>` | -| [I](test/-i) | `typealias I<T> = `[`H`](test/-h)`<T>` | +| [H](test/-h) | `typealias H<T> = `[`C`](test/-c/index)`<`[`T`](test/-h#T)`>` | +| [I](test/-i) | `typealias I<T> = `[`H`](test/-h)`<`[`T`](test/-i#T)`>` | | [J](test/-j) | `typealias J = `[`H`](test/-h)`<`[`A`](test/-a/index)`>` | | [K](test/-k) | `typealias K = `[`H`](test/-h)`<`[`J`](test/-j)`>` | | [L](test/-l) | `typealias L = (`[`K`](test/-k)`, `[`B`](test/-b/index)`) -> `[`J`](test/-j) | diff --git a/core/testdata/format/typeParameterBounds.md b/core/testdata/format/typeParameterBounds.md index 58df82a3..8f369ed6 100644 --- a/core/testdata/format/typeParameterBounds.md +++ b/core/testdata/format/typeParameterBounds.md @@ -2,7 +2,7 @@ # generic -`fun <T : R, R> generic(): Unit` +`fun <T : `[`R`](test/generic#R)`, R> generic(): Unit` generic function diff --git a/core/testdata/format/typeParameterReference.kt b/core/testdata/format/typeParameterReference.kt new file mode 100644 index 00000000..f196112d --- /dev/null +++ b/core/testdata/format/typeParameterReference.kt @@ -0,0 +1,6 @@ +/** + * Correct ref to [T] + */ +fun <T> T.tt() { + println("T.tt") +}
\ No newline at end of file diff --git a/core/testdata/format/typeParameterReference.md b/core/testdata/format/typeParameterReference.md new file mode 100644 index 00000000..ea49d48a --- /dev/null +++ b/core/testdata/format/typeParameterReference.md @@ -0,0 +1,8 @@ +[test](test/index) / [tt](test/tt) + +# tt + +`fun <T> `[`T`](test/tt#T)`.tt(): Unit` + +Correct ref to [T](test/tt#T) + diff --git a/core/testdata/format/typeProjectionVariance.md b/core/testdata/format/typeProjectionVariance.md index 5b8fc190..072b9fc7 100644 --- a/core/testdata/format/typeProjectionVariance.md +++ b/core/testdata/format/typeProjectionVariance.md @@ -2,5 +2,5 @@ ### Extensions for kotlin.Array -| [foo](test/kotlin.-array/foo) | `fun <T> Array<out T>.foo(): Unit` | +| [foo](test/kotlin.-array/foo) | `fun <T> Array<out `[`T`](test/kotlin.-array/foo#T)`>.foo(): Unit` | diff --git a/core/testdata/format/website-html/sampleWithAsserts.html b/core/testdata/format/website-html/sampleWithAsserts.html index e70d37c9..11a3a626 100644 --- a/core/testdata/format/website-html/sampleWithAsserts.html +++ b/core/testdata/format/website-html/sampleWithAsserts.html @@ -9,7 +9,14 @@ fun main(args: Array<String>) { //sampleStart println(a()) // Hello, Work println("a() == b() is ${a() == b()}") // true +// A eq B +println("a() == b() is ${a() == b()}") // true // readSomeFile(File("some.txt")) // reading file now will fail // readSomeFile(File("some.txt")) // will fail with FileNotFoundException + +fun indented() { + // A neq B + println("a() != b() is ${a() != b()}") // false +} //sampleEnd }</code></pre></div> diff --git a/core/testdata/format/website-html/sampleWithAsserts.kt b/core/testdata/format/website-html/sampleWithAsserts.kt index f5b03eb8..b3bce11d 100644 --- a/core/testdata/format/website-html/sampleWithAsserts.kt +++ b/core/testdata/format/website-html/sampleWithAsserts.kt @@ -22,6 +22,11 @@ fun readSomeFile(f: File) { fun sample() { assertPrints(a(), "Hello, Work") assertTrue(a() == b()) + assertTrue(a() == b(), "A eq B") assertFails("reading file now") { readSomeFile(File("some.txt")) } assertFailsWith<FileNotFoundException> { readSomeFile(File("some.txt")) } + + fun indented() { + assertFalse(a() != b(), "A neq B") + } }
\ No newline at end of file diff --git a/core/testdata/javadoc/companionMethodReference.kt b/core/testdata/javadoc/companionMethodReference.kt new file mode 100644 index 00000000..499e4492 --- /dev/null +++ b/core/testdata/javadoc/companionMethodReference.kt @@ -0,0 +1,13 @@ +package foo + + +/** + * Linking to [test] + */ +class TestClass { + + companion object { + + @JvmStatic fun test(arg: String) {} + } +}
\ No newline at end of file diff --git a/core/testdata/packages/classInPackage.kt b/core/testdata/packages/classInPackage.kt new file mode 100644 index 00000000..b22273af --- /dev/null +++ b/core/testdata/packages/classInPackage.kt @@ -0,0 +1,3 @@ +package simple.name + +class Foo {} diff --git a/gradle.properties b/gradle.properties index 44e510d6..cabae269 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,17 +2,18 @@ dokka_version=0.9.16 dokka_publication_channel=dokka #Kotlin compiler and plugin -kotlin_version=1.1.51 -kotlin_for_gradle_version=1.0.7 +bundled_kotlin_compiler_version=1.2.40-dev-529 +kotlin_version=1.2.21 +kotlin_for_gradle_runtime_version=1.1.60 ant_version=1.9.6 #Maven plugin dependencies -maven_version=3.0.5 +maven_version=3.5.0 maven_archiver_version=2.5 plexus_utils_version=3.0.22 plexus_archiver_version=3.4 -maven_plugin_tools_version=3.4 +maven_plugin_tools_version=3.5 #For CI mvn=mvn
\ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 26b61d74..610ad4c5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip diff --git a/integration/build.gradle b/integration/build.gradle index 55ac9dca..24d59edf 100644 --- a/integration/build.gradle +++ b/integration/build.gradle @@ -1,13 +1,26 @@ buildscript { dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_for_gradle_version" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin' + +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + languageVersion = "1.2" + apiVersion = "1.1" + jvmTarget = "1.8" + } +} + dependencies { - compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: kotlin_for_gradle_version - compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_version - compile 'com.github.yole:jkid:7d9c529c87' + compileOnly group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_for_gradle_runtime_version + compileOnly group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_runtime_version + compile('com.github.yole:jkid:8fc7f12e1a') { + transitive = false + } }
\ No newline at end of file diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/ReflectDsl.kt b/integration/src/main/kotlin/org/jetbrains/dokka/ReflectDsl.kt index 3c9bf156..1984a3e5 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/ReflectDsl.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/ReflectDsl.kt @@ -1,6 +1,8 @@ package org.jetbrains.dokka import kotlin.reflect.* +import kotlin.reflect.full.memberFunctions +import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.isAccessible object ReflectDsl { diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 4c4d479f..90e5b5fc 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -36,6 +36,8 @@ interface DokkaConfiguration { val impliedPlatforms: List<String> val perPackageOptions: List<PackageOptions> val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink> + val languageVersion: String? + val apiVersion: String? val noStdlibLink: Boolean val cacheRoot: String? val suppressedFiles: List<String> @@ -56,6 +58,7 @@ interface DokkaConfiguration { val includeNonPublic: Boolean val reportUndocumented: Boolean val skipDeprecated: Boolean + val suppress: Boolean } interface ExternalDocumentationLink { @@ -78,27 +81,31 @@ interface DokkaConfiguration { } } -data class SerializeOnlyDokkaConfiguration(override val moduleName: String, - override val classpath: List<String>, - override val sourceRoots: List<DokkaConfiguration.SourceRoot>, - override val samples: List<String>, - override val includes: List<String>, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>, - override val impliedPlatforms: List<String>, - override val perPackageOptions: List<DokkaConfiguration.PackageOptions>, - override val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List<String>) : DokkaConfiguration +data class SerializeOnlyDokkaConfiguration( + override val moduleName: String, + override val classpath: List<String>, + override val sourceRoots: List<DokkaConfiguration.SourceRoot>, + override val samples: List<String>, + override val includes: List<String>, + override val outputDir: String, + override val format: String, + override val includeNonPublic: Boolean, + override val includeRootPackage: Boolean, + override val reportUndocumented: Boolean, + override val skipEmptyPackages: Boolean, + override val skipDeprecated: Boolean, + override val jdkVersion: Int, + override val generateIndexPages: Boolean, + override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>, + override val impliedPlatforms: List<String>, + override val perPackageOptions: List<DokkaConfiguration.PackageOptions>, + override val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List<String>, + override val languageVersion: String?, + override val apiVersion: String? +) : DokkaConfiguration data class ExternalDocumentationLinkImpl(@CustomSerializer(UrlSerializer::class) override val url: URL, diff --git a/lib/intellij-core-analysis.jar b/lib/intellij-core-analysis.jar Binary files differdeleted file mode 100644 index 50520e0c..00000000 --- a/lib/intellij-core-analysis.jar +++ /dev/null diff --git a/lib/kotlin-ide-common.jar b/lib/kotlin-ide-common.jar Binary files differdeleted file mode 100644 index 98648313..00000000 --- a/lib/kotlin-ide-common.jar +++ /dev/null diff --git a/lib/markdown.jar b/lib/markdown.jar Binary files differdeleted file mode 100644 index e61f954c..00000000 --- a/lib/markdown.jar +++ /dev/null diff --git a/runners/android-gradle-plugin/build.gradle b/runners/android-gradle-plugin/build.gradle index 8e97d9d9..72d1be9e 100644 --- a/runners/android-gradle-plugin/build.gradle +++ b/runners/android-gradle-plugin/build.gradle @@ -1,13 +1,22 @@ +import com.gradle.publish.DependenciesBuilder +import org.jetbrains.CorrectShadowPublishing + apply plugin: 'java' apply plugin: 'kotlin' -sourceCompatibility = 1.8 apply plugin: 'com.github.johnrengelman.shadow' apply plugin: "com.gradle.plugin-publish" -tasks.withType(AbstractCompile) { - classpath += configurations.shadow +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + freeCompilerArgs += "-Xjsr305=strict" + languageVersion = "1.2" + apiVersion = "1.1" + jvmTarget = "1.8" + } } repositories { @@ -47,13 +56,14 @@ apply plugin: 'maven-publish' publishing { publications { - dokkaAndroidGradlePlugin(MavenPublication) { publication -> + dokkaAndroidGradlePlugin(MavenPublication) { MavenPublication publication -> artifactId = 'dokka-android-gradle-plugin' artifact sourceJar { classifier "sources" } - project.shadow.component(publication) + + CorrectShadowPublishing.configure(publication, project) } } } @@ -78,6 +88,12 @@ pluginBundle { } } + withDependencies { List<Dependency> list -> + list.clear() + def builder = new DependenciesBuilder() + builder.addUniqueScopedDependencies(list, configurations.shadow, "compile") + } + mavenCoordinates { groupId = "org.jetbrains.dokka" artifactId = "dokka-android-gradle-plugin" diff --git a/runners/ant/build.gradle b/runners/ant/build.gradle index 85328d95..e7dcd441 100644 --- a/runners/ant/build.gradle +++ b/runners/ant/build.gradle @@ -1,6 +1,15 @@ apply plugin: 'kotlin' -sourceCompatibility = 1.6 +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + freeCompilerArgs += "-Xjsr305=strict" + languageVersion = "1.2" + apiVersion = languageVersion + jvmTarget = "1.8" + } +} dependencies { compile project(":core") diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index fb70aefd..d1b6bef5 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -28,7 +28,8 @@ class AntPackageOptions( override var prefix: String = "", override var includeNonPublic: Boolean = false, override var reportUndocumented: Boolean = true, - override var skipDeprecated: Boolean = false) : DokkaConfiguration.PackageOptions + override var skipDeprecated: Boolean = false, + override var suppress: Boolean = false) : DokkaConfiguration.PackageOptions class DokkaAntTask: Task() { @@ -44,6 +45,9 @@ class DokkaAntTask: Task() { var cacheRoot: String? = null + var languageVersion: String? = null + var apiVersion: String? = null + val compileClasspath: Path by lazy { Path(getProject()) } val sourcePath: Path by lazy { Path(getProject()) } val samplesPath: Path by lazy { Path(getProject()) } @@ -117,7 +121,9 @@ class DokkaAntTask: Task() { samplesPath.list().toList(), includesPath.list().toList(), moduleName!!, - DocumentationOptions(outputDir!!, outputFormat, + DocumentationOptions( + outputDir!!, + outputFormat, skipDeprecated = skipDeprecated, sourceLinks = sourceLinks, jdkVersion = jdkVersion, @@ -125,7 +131,9 @@ class DokkaAntTask: Task() { perPackageOptions = antPackageOptions, externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, noStdlibLink = noStdlibLink, - cacheRoot = cacheRoot + cacheRoot = cacheRoot, + languageVersion = languageVersion, + apiVersion = apiVersion ) ) generator.generate() diff --git a/runners/build.gradle b/runners/build.gradle index f1d2873c..23d232d2 100644 --- a/runners/build.gradle +++ b/runners/build.gradle @@ -1,15 +1,7 @@ -configure([project("ant"), project("cli"), project("fatjar"), project("maven-plugin")]) { +subprojects { buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } -} - -configure([project("gradle-plugin"), project("android-gradle-plugin"), project("gradle-integration-tests")]) { - buildscript { - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_for_gradle_version" - } - } -} +}
\ No newline at end of file diff --git a/runners/cli/build.gradle b/runners/cli/build.gradle index 13b0c941..7f733140 100644 --- a/runners/cli/build.gradle +++ b/runners/cli/build.gradle @@ -1,6 +1,14 @@ apply plugin: 'kotlin' -sourceCompatibility = 1.6 +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + languageVersion = "1.2" + apiVersion = languageVersion + jvmTarget = "1.8" + } +} dependencies { compile project(":core") diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index c12166c5..fe945ed3 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -44,7 +44,7 @@ class DokkaArguments { @set:Argument(value = "impliedPlatforms", description = "List of implied platforms (comma-separated)") var impliedPlatforms: String = "" - @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented;...\" ") + @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ") var packageOptions: String = "" @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...") @@ -55,6 +55,13 @@ class DokkaArguments { @set:Argument(value = "cacheRoot", description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled") var cacheRoot: String? = null + + @set:Argument(value = "languageVersion", description = "Language Version to pass to Kotlin Analysis") + var languageVersion: String? = null + + @set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis") + var apiVersion: String? = null + } @@ -108,7 +115,9 @@ object MainKt { jdkVersion = arguments.jdkVersion, externalDocumentationLinks = parseLinks(arguments.links), noStdlibLink = arguments.noStdlibLink, - cacheRoot = arguments.cacheRoot + cacheRoot = arguments.cacheRoot, + languageVersion = arguments.languageVersion, + apiVersion = arguments.apiVersion ) val generator = DokkaGenerator( @@ -139,8 +148,10 @@ object MainKt { fun createClassLoaderWithTools(): ClassLoader { val toolsJar = findToolsJar().canonicalFile.toURI().toURL() + val originalUrls = (javaClass.classLoader as? URLClassLoader)?.urLs val dokkaJar = javaClass.protectionDomain.codeSource.location - return URLClassLoader(arrayOf(toolsJar, dokkaJar), ClassLoader.getSystemClassLoader().parent) + val urls = if (originalUrls != null) arrayOf(toolsJar, *originalUrls) else arrayOf(toolsJar, dokkaJar) + return URLClassLoader(urls, ClassLoader.getSystemClassLoader().parent) } fun startWithToolsJar(args: Array<String>) { diff --git a/runners/fatjar/build.gradle b/runners/fatjar/build.gradle index e3bea7ed..4ce0416c 100644 --- a/runners/fatjar/build.gradle +++ b/runners/fatjar/build.gradle @@ -1,7 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.ServiceFileTransformer import org.jetbrains.PluginXmlTransformer -apply plugin: 'kotlin' +apply plugin: 'java' apply plugin: 'com.github.johnrengelman.shadow' dependencies { @@ -30,6 +30,10 @@ shadowJar { exclude 'fileTemplates/**' exclude 'inspectionDescriptions/**' exclude 'intentionDescriptions/**' + + exclude 'src/**' + + relocate('kotlin.reflect.full', 'kotlin.reflect') } apply plugin: 'maven-publish' diff --git a/runners/gradle-integration-tests/android-licenses/android-sdk-license b/runners/gradle-integration-tests/android-licenses/android-sdk-license new file mode 100644 index 00000000..c311cf48 --- /dev/null +++ b/runners/gradle-integration-tests/android-licenses/android-sdk-license @@ -0,0 +1,2 @@ + +d56f5187479451eabf01fb78af6dfcb131a6481e
\ No newline at end of file diff --git a/runners/gradle-integration-tests/android-licenses/android-sdk-preview-license b/runners/gradle-integration-tests/android-licenses/android-sdk-preview-license new file mode 100644 index 00000000..da4552d2 --- /dev/null +++ b/runners/gradle-integration-tests/android-licenses/android-sdk-preview-license @@ -0,0 +1,2 @@ + +84831b9409646a918e30573bab4c9c91346d8abd
\ No newline at end of file diff --git a/runners/gradle-integration-tests/build.gradle b/runners/gradle-integration-tests/build.gradle index 179b6455..a681c82e 100644 --- a/runners/gradle-integration-tests/build.gradle +++ b/runners/gradle-integration-tests/build.gradle @@ -2,6 +2,16 @@ apply plugin: 'kotlin' +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + freeCompilerArgs += "-Xjsr305=strict" + languageVersion = "1.2" + apiVersion = "1.0" + jvmTarget = "1.8" + } +} configurations { dokkaPlugin @@ -11,9 +21,9 @@ configurations { dependencies { - testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: kotlin_for_gradle_version - testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_version - testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test', version: kotlin_for_gradle_version + testCompileOnly group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_for_gradle_runtime_version + testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlin_for_gradle_runtime_version + testCompile ideaRT() dokkaPlugin project(path: ':runners:gradle-plugin', configuration: 'shadow') dokkaAndroidPlugin project(path: ':runners:android-gradle-plugin', configuration: 'shadow') @@ -42,4 +52,8 @@ task createClasspathManifest { createClasspathManifest.mustRunAfter project(":runners:fatjar").shadowJar testClasses.dependsOn project(":runners:fatjar").shadowJar -testClasses.dependsOn createClasspathManifest
\ No newline at end of file +testClasses.dependsOn createClasspathManifest + +test { + systemProperty "android.licenses.overwrite", project.findProperty("android.licenses.overwrite") ?: "" +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java b/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java deleted file mode 100644 index cbb1cc3c..00000000 --- a/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/FileComparisonFailure.java +++ /dev/null @@ -1,39 +0,0 @@ - -package com.intellij.rt.execution.junit; - -import junit.framework.ComparisonFailure; - -public class FileComparisonFailure extends ComparisonFailure implements KnownException { - private final String myExpected; - private final String myActual; - private final String myFilePath; - private final String myActualFilePath; - - public FileComparisonFailure(String message, String expected, String actual, String filePath) { - this(message, expected, actual, filePath, (String)null); - } - - public FileComparisonFailure(String message, String expected, String actual, String expectedFilePath, String actualFilePath) { - super(message, expected, actual); - this.myExpected = expected; - this.myActual = actual; - this.myFilePath = expectedFilePath; - this.myActualFilePath = actualFilePath; - } - - public String getFilePath() { - return this.myFilePath; - } - - public String getActualFilePath() { - return this.myActualFilePath; - } - - public String getExpected() { - return this.myExpected; - } - - public String getActual() { - return this.myActual; - } -} diff --git a/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java b/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java deleted file mode 100644 index c24653ea..00000000 --- a/runners/gradle-integration-tests/src/test/java/com/intellij/rt/execution/junit/KnownException.java +++ /dev/null @@ -1,6 +0,0 @@ - -package com.intellij.rt.execution.junit; - -interface KnownException { - -} diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractAndroidAppTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractAndroidAppTest.kt new file mode 100644 index 00000000..c3fe2ea9 --- /dev/null +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractAndroidAppTest.kt @@ -0,0 +1,51 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.testkit.runner.TaskOutcome +import kotlin.test.assertEquals + +abstract class AbstractAndroidAppTest(val testDataRootPath: String) : AbstractDokkaAndroidGradleTest() { + + fun prepareTestData() { + val testDataRoot = testDataFolder.resolve(testDataRootPath) + val tmpRoot = testProjectDir.root.toPath() + + testDataRoot.resolve("app").copy(tmpRoot.resolve("app")) + testDataRoot.resolve("build.gradle").copy(tmpRoot.resolve("build.gradle")) + testDataRoot.resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle")) + + androidLocalProperties?.copy(tmpRoot.resolve("local.properties")) + } + + + data class AndroidPluginParams(val pluginVersion: String, val buildToolsVersion: String, val compileSdk: Int) { + fun asArguments(): List<String> = listOf( + "-Pabt_plugin_version=$pluginVersion", + "-Pabt_version=$buildToolsVersion", + "-Psdk_version=$compileSdk" + ) + } + + + protected fun doTest(gradleVersion: String, kotlinVersion: String, androidPluginParams: AndroidPluginParams) { + prepareTestData() + + val result = configure(gradleVersion, kotlinVersion, + arguments = arrayOf("dokka", "--stacktrace") + androidPluginParams.asArguments()) + .build() + + println(result.output) + + assertEquals(TaskOutcome.SUCCESS, result.task(":app:dokka")?.outcome) + + val docsOutput = "app/build/dokka" + + checkOutputStructure("$testDataRootPath/fileTree.txt", docsOutput) + + checkNoErrorClasses(docsOutput) + checkNoUnresolvedLinks(docsOutput) + + checkExternalLink(docsOutput, "<span class=\"identifier\">Activity</span>", + """<a href="https://developer.android.com/reference/android/app/Activity.html"><span class="identifier">Activity</span></a>""") + } + +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt new file mode 100644 index 00000000..06753342 --- /dev/null +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt @@ -0,0 +1,45 @@ +package org.jetbrains.dokka.gradle + +import org.junit.BeforeClass +import java.io.File + +abstract class AbstractDokkaAndroidGradleTest : AbstractDokkaGradleTest() { + + override val pluginClasspath: List<File> = androidPluginClasspathData.toFile().readLines().map { File(it) } + + companion object { + + @JvmStatic + @BeforeClass + fun acceptAndroidSdkLicenses() { + val sdkDir = androidLocalProperties?.toFile()?.let { + val lines = it.readLines().map { it.trim() } + val sdkDirLine = lines.firstOrNull { "sdk.dir" in it } + sdkDirLine?.substringAfter("=")?.trim() + } ?: System.getenv("ANDROID_HOME") + + if (sdkDir == null || sdkDir.isEmpty()) { + error("Android SDK home not set, " + + "try setting \$ANDROID_HOME " + + "or sdk.dir in runners/gradle-integration-tests/testData/android.local.properties") + } + val sdkDirFile = File(sdkDir) + if (!sdkDirFile.exists()) error("\$ANDROID_HOME and android.local.properties points to non-existing location") + val sdkLicensesDir = sdkDirFile.resolve("licenses") + + val acceptedLicenses = File("android-licenses") + acceptedLicenses.listFiles().forEach { licenseFile -> + val target = sdkLicensesDir.resolve(licenseFile.name) + if(!target.exists() || target.readText() != licenseFile.readText()) { + val overwrite = System.getProperty("android.licenses.overwrite", "false").toBoolean() + if (!target.exists() || overwrite) { + licenseFile.copyTo(target, true) + println("Accepted ${licenseFile.name}, by copying $licenseFile to $target") + } + } + + } + } + + } +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidAppTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidAppTest.kt index de22a980..bbb63909 100644 --- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidAppTest.kt +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidAppTest.kt @@ -1,66 +1,25 @@ package org.jetbrains.dokka.gradle -import org.gradle.testkit.runner.TaskOutcome import org.junit.Test -import java.io.File -import java.nio.file.Files -import kotlin.test.assertEquals -class AndroidAppTest : AbstractDokkaGradleTest() { - override val pluginClasspath: List<File> = androidPluginClasspathData.toFile().readLines().map { File(it) } - - fun prepareTestData(testDataRootPath: String) { - val testDataRoot = testDataFolder.resolve(testDataRootPath) - val tmpRoot = testProjectDir.root.toPath() - - testDataRoot.resolve("app").copy(tmpRoot.resolve("app")) - testDataRoot.resolve("build.gradle").copy(tmpRoot.resolve("build.gradle")) - testDataRoot.resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle")) - - androidLocalProperties?.copy(tmpRoot.resolve("local.properties")) - } - - - data class AndroidPluginParams(val pluginVersion: String, val buildToolsVersion: String, val compileSdk: Int) { - fun asArguments(): List<String> = listOf( - "-Pabt_plugin_version=$pluginVersion", - "-Pabt_version=$buildToolsVersion", - "-Psdk_version=$compileSdk" - ) - } - - - private fun doTest(gradleVersion: String, kotlinVersion: String, androidPluginParams: AndroidPluginParams) { - prepareTestData("androidApp") - - val result = configure(gradleVersion, kotlinVersion, - arguments = arrayOf("dokka", "--stacktrace") + androidPluginParams.asArguments()) - .build() - - println(result.output) - - assertEquals(TaskOutcome.SUCCESS, result.task(":app:dokka")?.outcome) - - val docsOutput = "app/build/dokka" - - checkOutputStructure("androidApp/fileTree.txt", docsOutput) - - checkNoErrorClasses(docsOutput) - checkNoUnresolvedLinks(docsOutput) - - checkExternalLink(docsOutput, "<span class=\"identifier\">Activity</span>", - """<a href="https://developer.android.com/reference/android/app/Activity.html"><span class="identifier">Activity</span></a>""") - } - - @Test fun `test kotlin 1_1_2-5 and gradle 4_0 and abt 3_0_0-alpha3`() { +class AndroidAppTest : AbstractAndroidAppTest("androidApp") { + @Test + fun `test kotlin 1_1_2-5 and gradle 4_0 and abt 3_0_0-alpha3`() { doTest("4.0", "1.1.2-5", AndroidPluginParams("3.0.0-alpha3", "25.0.2", 25)) } - @Test fun `test kotlin 1_1_2 and gradle 3_5 and abt 2_3_0`() { + @Test + fun `test kotlin 1_1_2 and gradle 3_5 and abt 2_3_0`() { doTest("3.5", "1.1.2", AndroidPluginParams("2.3.0", "25.0.0", 24)) } - @Test fun `test kotlin 1_0_7 and gradle 2_14_1 and abt 2_2_3`() { + @Test + fun `test kotlin 1_0_7 and gradle 2_14_1 and abt 2_2_3`() { doTest("2.14.1", "1.0.7", AndroidPluginParams("2.2.3", "25.0.0", 24)) } + + @Test + fun `test kotlin 1_2_20 and gradle 4_5 and abt 3_0_1`() { + doTest("4.5", "1.2.20", AndroidPluginParams("3.0.1", "27.0.0", 27)) + } }
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidMultiFlavourAppTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidMultiFlavourAppTest.kt index aee0e14c..ef1b94d8 100644 --- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidMultiFlavourAppTest.kt +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidMultiFlavourAppTest.kt @@ -1,13 +1,11 @@ package org.jetbrains.dokka.gradle import org.gradle.testkit.runner.TaskOutcome -import org.jetbrains.dokka.gradle.AndroidAppTest.AndroidPluginParams +import org.jetbrains.dokka.gradle.AbstractAndroidAppTest.AndroidPluginParams import org.junit.Test -import java.io.File import kotlin.test.assertEquals -class AndroidMultiFlavourAppTest : AbstractDokkaGradleTest() { - override val pluginClasspath: List<File> = androidPluginClasspathData.toFile().readLines().map { File(it) } +class AndroidMultiFlavourAppTest : AbstractDokkaAndroidGradleTest() { fun prepareTestData(testDataRootPath: String) { val testDataRoot = testDataFolder.resolve(testDataRootPath) @@ -55,4 +53,8 @@ class AndroidMultiFlavourAppTest : AbstractDokkaGradleTest() { doTest("2.14.1", "1.0.7", AndroidPluginParams("2.2.3", "25.0.0", 24)) } + @Test fun `test kotlin 1_2_20 and gradle 4_5 and abt 3_0_1`() { + doTest("4.5", "1.2.20", AndroidPluginParams("3.0.1", "27.0.0", 27)) + } + }
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt index f9801c82..ebaf1653 100644 --- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt @@ -11,6 +11,7 @@ class BasicTest : AbstractDokkaGradleTest() { val tmpRoot = testProjectDir.root.toPath() testDataRoot.resolve("src").copy(tmpRoot.resolve("src")) + testDataRoot.resolve("classDir").copy(tmpRoot.resolve("classDir")) testDataRoot.resolve("build.gradle").copy(tmpRoot.resolve("build.gradle")) testDataRoot.resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle")) } @@ -48,4 +49,7 @@ class BasicTest : AbstractDokkaGradleTest() { doTest("4.0", "1.1.2") } + @Test fun `test kotlin 1_2_20 and gradle 4_5`() { + doTest("4.5", "1.2.20") + } }
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/JavadocRSuppressionTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/JavadocRSuppressionTest.kt new file mode 100644 index 00000000..3a4d08b8 --- /dev/null +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/JavadocRSuppressionTest.kt @@ -0,0 +1,24 @@ +package org.jetbrains.dokka.gradle + +import org.junit.Test + +class JavadocRSuppressionTest : AbstractAndroidAppTest("androidAppJavadoc") { + @Test + fun `test kotlin 1_1_2-5 and gradle 4_0 and abt 3_0_0-alpha3`() { + doTest("4.0", "1.1.2-5", AndroidPluginParams("3.0.0-alpha3", "25.0.2", 25)) + } + + @Test + fun `test kotlin 1_1_2 and gradle 3_5 and abt 2_3_0`() { + doTest("3.5", "1.1.2", AndroidPluginParams("2.3.0", "25.0.0", 24)) + } + + @Test + fun `test kotlin 1_0_7 and gradle 2_14_1 and abt 2_2_3`() { + doTest("2.14.1", "1.0.7", AndroidPluginParams("2.2.3", "25.0.0", 24)) + } + + @Test fun `test kotlin 1_2_20 and gradle 4_5 and abt 3_0_1`() { + doTest("4.5", "1.2.20", AndroidPluginParams("3.0.1", "27.0.0", 27)) + } +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt index 13c7c37e..9458528c 100644 --- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiProjectSingleOutTest.kt @@ -51,4 +51,7 @@ class MultiProjectSingleOutTest : AbstractDokkaGradleTest() { doTest("4.0", "1.1.2") } + @Test fun `test kotlin 1_2_20 and gradle 4_5`() { + doTest("4.5", "1.2.20") + } }
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt new file mode 100644 index 00000000..f712998c --- /dev/null +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt @@ -0,0 +1,74 @@ +package org.jetbrains.dokka.gradle + +import org.gradle.testkit.runner.TaskOutcome +import org.junit.Test +import java.nio.file.Path +import kotlin.test.assertEquals + +class RebuildAfterSourceChangeTest : AbstractDokkaGradleTest() { + + fun prepareTestData(testDataRootPath: String): Pair<Path, Path> { + val testDataRoot = testDataFolder.resolve(testDataRootPath) + val tmpRoot = testProjectDir.root.toPath() + + testDataRoot.resolve("src").copy(tmpRoot.resolve("src")) + testDataRoot.resolve("build.gradle").copy(tmpRoot.resolve("build.gradle")) + testDataRoot.resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle")) + + return testDataRoot to tmpRoot + } + + private fun doTest(gradleVersion: String, kotlinVersion: String) { + + val (testDataRoot, tmpRoot) = prepareTestData("sourcesChange") + val docsOutput = "build/dokka" + + configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build().let { result -> + println(result.output) + + assertEquals(TaskOutcome.SUCCESS, result.task(":dokka")?.outcome) + } + + + configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build().let { result -> + println(result.output) + + assertEquals(TaskOutcome.UP_TO_DATE, result.task(":dokka")?.outcome) + } + + checkOutputStructure("sourcesChange/fileTree.txt", docsOutput) + + testDataRoot.resolve("src1").copy(tmpRoot.resolve("src")) + + configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build().let { result -> + println(result.output) + + assertEquals(TaskOutcome.SUCCESS, result.task(":dokka")?.outcome) + } + + + checkOutputStructure("sourcesChange/fileTree1.txt", docsOutput) + + } + + + @Test + fun `test kotlin 1_1_2 and gradle 3_5`() { + doTest("3.5", "1.1.2") + } + + @Test + fun `test kotlin 1_0_7 and gradle 2_14_1`() { + doTest("2.14.1", "1.0.7") + } + + @Test + fun `test kotlin 1_1_2 and gradle 4_0`() { + doTest("4.0", "1.1.2") + } + + @Test + fun `test kotlin 1_2_20 and gradle 4_5`() { + doTest("4.5", "1.2.20") + } +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt index d44459b1..6f17af22 100644 --- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/Utils.kt @@ -3,10 +3,7 @@ package org.jetbrains.dokka.gradle import com.intellij.rt.execution.junit.FileComparisonFailure import java.io.File import java.io.IOException -import java.nio.file.FileVisitResult -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.SimpleFileVisitor +import java.nio.file.* import java.nio.file.attribute.BasicFileAttributes @@ -48,7 +45,7 @@ class CopyFileVisitor(private var sourcePath: Path?, private val targetPath: Pat @Throws(IOException::class) override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult { - Files.copy(file, targetPath.resolve(sourcePath?.relativize(file))) + Files.copy(file, targetPath.resolve(sourcePath?.relativize(file)), StandardCopyOption.REPLACE_EXISTING) return FileVisitResult.CONTINUE } } diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle new file mode 100644 index 00000000..6a053a5e --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle @@ -0,0 +1,50 @@ +buildscript { + repositories { + jcenter() + mavenLocal() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version" + } +} + +plugins { + id 'org.jetbrains.dokka-android' +} + + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'org.jetbrains.dokka-android' + +android { + compileSdkVersion Integer.parseInt(sdk_version) + buildToolsVersion abt_version + + defaultConfig { + applicationId "org.example.kotlin.mixed" + minSdkVersion 14 + targetSdkVersion Integer.parseInt(sdk_version) + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt') + } + } + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version" +} + + +dokka { + outputFormat = "javadoc" + dokkaFatJar = new File(dokka_fatjar) +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/AndroidManifest.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..b4e1a892 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.example.kotlin.mixed" > + + <application + android:allowBackup="true" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + + <activity + android:name=".JavaActivity" + android:label="@string/title_activity_main_activity1" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity + android:name=".KotlinActivity" + android:label="@string/title_activity_main_activity2" /> + + </application> + +</manifest> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/java/org/example/kotlin/mixed/JavaActivity.java b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/java/org/example/kotlin/mixed/JavaActivity.java new file mode 100644 index 00000000..3668c594 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/java/org/example/kotlin/mixed/JavaActivity.java @@ -0,0 +1,34 @@ +package org.example.kotlin.mixed; + +import android.content.Intent; +import android.os.Bundle; +import android.app.Activity; +import android.view.Menu; +import android.view.View; +import android.widget.Button; + +public class JavaActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Button next = (Button) findViewById(R.id.Button01); + next.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + Intent myIntent = new Intent(view.getContext(), KotlinActivity.class); + startActivityForResult(myIntent, 0); + } + }); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + +} diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/kotlin/org/example/kotlin/mixed/KotlinActivity.kt b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/kotlin/org/example/kotlin/mixed/KotlinActivity.kt new file mode 100644 index 00000000..ca2f27b0 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/kotlin/org/example/kotlin/mixed/KotlinActivity.kt @@ -0,0 +1,28 @@ +package org.example.kotlin.mixed + +import android.content.Intent +import android.os.Bundle +import android.app.Activity +import android.view.Menu +import android.widget.Button + +class KotlinActivity : Activity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main2) + + val next = findViewById(R.id.Button02) as Button + next.setOnClickListener { + val intent: Intent = Intent() + setResult(RESULT_OK, intent) + finish() + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.main_activity2, menu) + return true + } +} diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-hdpi/ic_launcher.png b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..96a442e5 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-mdpi/ic_launcher.png b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..359047df --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-xhdpi/ic_launcher.png b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..71c6d760 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/layout/activity_main.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..ede57c39 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,24 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context=".MainActivity"> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="Activity 1" /> + + <Button android:text="Next" + android:id="@+id/Button01" + android:layout_width="250px" + android:textSize="18px" + android:layout_height="55px"> + </Button> + +</LinearLayout> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/layout/activity_main2.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/layout/activity_main2.xml new file mode 100644 index 00000000..d707536a --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/layout/activity_main2.xml @@ -0,0 +1,24 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context=".MainActivity"> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="Activity 2" /> + + <Button android:text="Next" + android:id="@+id/Button02" + android:layout_width="250px" + android:textSize="18px" + android:layout_height="55px"> + </Button> + +</LinearLayout> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/menu/main.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/menu/main.xml new file mode 100644 index 00000000..f3b10b6c --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/menu/main.xml @@ -0,0 +1,6 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/action_settings" + android:title="@string/action_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/menu/main_activity2.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/menu/main_activity2.xml new file mode 100644 index 00000000..f3b10b6c --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/menu/main_activity2.xml @@ -0,0 +1,6 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/action_settings" + android:title="@string/action_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/dimens.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/dimens.xml new file mode 100644 index 00000000..47c82246 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ +<resources> + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="activity_horizontal_margin">16dp</dimen> + <dimen name="activity_vertical_margin">16dp</dimen> +</resources> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/strings.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..d8f08bc2 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="app_name">AndroidSample</string> + <string name="action_settings">Settings</string> + <string name="hello_world">Hello world!</string> + <string name="title_activity_main_activity1">JavaActivity</string> + <string name="title_activity_main_activity2">KotlinActivity</string> + +</resources> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/styles.xml b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..6ce89c7b --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ +<resources> + + <!-- + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Light"> + <!-- + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + --> + </style> + + <!-- Application theme. --> + <style name="AppTheme" parent="AppBaseTheme"> + <!-- All customizations that are NOT specific to a particular API-level can go here. --> + </style> + +</resources> diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle b/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle new file mode 100644 index 00000000..59477b52 --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle @@ -0,0 +1,21 @@ +buildscript { + repositories { + mavenCentral() + jcenter() + maven { url 'https://maven.google.com' } + maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } + } + dependencies { + classpath "com.android.tools.build:gradle:$abt_plugin_version" + } +} + +allprojects { + repositories { + mavenCentral() + jcenter() + maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } + } +} diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/fileTree.txt b/runners/gradle-integration-tests/testData/androidAppJavadoc/fileTree.txt new file mode 100644 index 00000000..c5e79eba --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/fileTree.txt @@ -0,0 +1,21 @@ +/ + allclasses-frame.html + allclasses-noframe.html + constant-values.html + deprecated-list.html + help-doc.html + index-all.html + index.html + org/ + example/ + kotlin/ + mixed/ + JavaActivity.html + KotlinActivity.html + package-frame.html + package-summary.html + package-tree.html + overview-tree.html + package-list + script.js + stylesheet.css diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/settings.gradle b/runners/gradle-integration-tests/testData/androidAppJavadoc/settings.gradle new file mode 100644 index 00000000..a4e67fea --- /dev/null +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = "androidAppJavadoc" + +include ':app'
\ No newline at end of file diff --git a/runners/gradle-integration-tests/testData/basic/build.gradle b/runners/gradle-integration-tests/testData/basic/build.gradle index bc20e1cf..4a259f50 100644 --- a/runners/gradle-integration-tests/testData/basic/build.gradle +++ b/runners/gradle-integration-tests/testData/basic/build.gradle @@ -36,4 +36,5 @@ dependencies { dokka { dokkaFatJar = new File(dokka_fatjar) + classpath += files("$projectDir/classDir") }
\ No newline at end of file diff --git a/runners/gradle-integration-tests/testData/basic/classDir/p1/MyBinaryClass.class b/runners/gradle-integration-tests/testData/basic/classDir/p1/MyBinaryClass.class Binary files differnew file mode 100644 index 00000000..ccfff300 --- /dev/null +++ b/runners/gradle-integration-tests/testData/basic/classDir/p1/MyBinaryClass.class diff --git a/runners/gradle-integration-tests/testData/basic/fileTree.txt b/runners/gradle-integration-tests/testData/basic/fileTree.txt index 1a483d4e..2ceae371 100644 --- a/runners/gradle-integration-tests/testData/basic/fileTree.txt +++ b/runners/gradle-integration-tests/testData/basic/fileTree.txt @@ -22,6 +22,9 @@ constructor.html index.html main.html + p1.-my-binary-class/ + index.html + test.html str.html x.html index-outline.html diff --git a/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt b/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt index 7492e2a8..3d7bcb51 100644 --- a/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt +++ b/runners/gradle-integration-tests/testData/basic/src/main/kotlin/demo/HelloWorld.kt @@ -1,5 +1,7 @@ package demo +import p1.MyBinaryClass + /** * This class supports greeting people by name. * @@ -39,3 +41,5 @@ fun SomeType.constructor(): SomeType { annotation class A(val p: String) +val MyBinaryClass.test get() = s() + diff --git a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle new file mode 100644 index 00000000..bc20e1cf --- /dev/null +++ b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle @@ -0,0 +1,39 @@ +buildscript { + repositories { + mavenCentral() + jcenter() + maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version" + } +} + +plugins { + id 'org.jetbrains.dokka' +} + +apply plugin: 'kotlin' +apply plugin: 'org.jetbrains.dokka' + +repositories { + mavenCentral() + jcenter() + maven { + url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" + } + maven { + url "https://dl.bintray.com/kotlin/kotlin-dev" + } +} + +dependencies { + compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version + compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version +} + + +dokka { + dokkaFatJar = new File(dokka_fatjar) +}
\ No newline at end of file diff --git a/runners/gradle-integration-tests/testData/sourcesChange/fileTree.txt b/runners/gradle-integration-tests/testData/sourcesChange/fileTree.txt new file mode 100644 index 00000000..09f3724b --- /dev/null +++ b/runners/gradle-integration-tests/testData/sourcesChange/fileTree.txt @@ -0,0 +1,10 @@ +/ + sources-change/ + alltypes.html + demo/ + hello.html + index.html + index-outline.html + index.html + package-list + style.css diff --git a/runners/gradle-integration-tests/testData/sourcesChange/fileTree1.txt b/runners/gradle-integration-tests/testData/sourcesChange/fileTree1.txt new file mode 100644 index 00000000..eeb377f7 --- /dev/null +++ b/runners/gradle-integration-tests/testData/sourcesChange/fileTree1.txt @@ -0,0 +1,11 @@ +/ + sources-change/ + alltypes.html + demo/ + hello.html + index.html + world.html + index-outline.html + index.html + package-list + style.css diff --git a/runners/gradle-integration-tests/testData/sourcesChange/settings.gradle b/runners/gradle-integration-tests/testData/sourcesChange/settings.gradle new file mode 100644 index 00000000..3fb032bf --- /dev/null +++ b/runners/gradle-integration-tests/testData/sourcesChange/settings.gradle @@ -0,0 +1 @@ +rootProject.name = "sourcesChange"
\ No newline at end of file diff --git a/runners/gradle-integration-tests/testData/sourcesChange/src/main/kotlin/demo/HelloWorld.kt b/runners/gradle-integration-tests/testData/sourcesChange/src/main/kotlin/demo/HelloWorld.kt new file mode 100644 index 00000000..c54dea50 --- /dev/null +++ b/runners/gradle-integration-tests/testData/sourcesChange/src/main/kotlin/demo/HelloWorld.kt @@ -0,0 +1,6 @@ +package demo + +/** + * @return Hello + */ +fun hello(): String = "Hello"
\ No newline at end of file diff --git a/runners/gradle-integration-tests/testData/sourcesChange/src1/main/kotlin/demo/HelloWorld.kt b/runners/gradle-integration-tests/testData/sourcesChange/src1/main/kotlin/demo/HelloWorld.kt new file mode 100644 index 00000000..53f22ff5 --- /dev/null +++ b/runners/gradle-integration-tests/testData/sourcesChange/src1/main/kotlin/demo/HelloWorld.kt @@ -0,0 +1,11 @@ +package demo + +/** + * @return Hello + */ +fun hello(): String = "Hello" + +/** + * @return World + */ +fun world(): String = "World"
\ No newline at end of file diff --git a/runners/gradle-plugin/build.gradle b/runners/gradle-plugin/build.gradle index 5af6b427..661d432b 100644 --- a/runners/gradle-plugin/build.gradle +++ b/runners/gradle-plugin/build.gradle @@ -1,20 +1,28 @@ +import com.gradle.publish.DependenciesBuilder + apply plugin: 'java' apply plugin: 'kotlin' -sourceCompatibility = 1.8 apply plugin: 'com.github.johnrengelman.shadow' apply plugin: "com.gradle.plugin-publish" -tasks.withType(AbstractCompile) { - classpath += configurations.shadow +sourceCompatibility = 1.8 + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + freeCompilerArgs += "-Xjsr305=strict" + languageVersion = "1.2" + apiVersion = "1.1" + jvmTarget = "1.8" + } } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' - shadow group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: kotlin_for_gradle_version - shadow group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_version + shadow group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_for_gradle_runtime_version + shadow group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_runtime_version compile project(":integration") @@ -78,6 +86,12 @@ pluginBundle { } } + withDependencies { List<Dependency> list -> + list.clear() + def builder = new DependenciesBuilder() + builder.addUniqueScopedDependencies(list, configurations.shadow, "compile") + } + mavenCoordinates { groupId = "org.jetbrains.dokka" artifactId = "dokka-gradle-plugin" diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 37feccc9..8c7f608e 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -51,6 +51,8 @@ object ClassloaderContainer { var fatJarClassLoader: ClassLoader? = null } +const val `deprecationMessage reportNotDocumented` = "Will be removed in 0.9.17, see dokka#243" + open class DokkaTask : DefaultTask() { fun defaultKotlinTasks() = with(ReflectDsl) { @@ -69,7 +71,7 @@ open class DokkaTask : DefaultTask() { description = "Generates dokka documentation for Kotlin" @Suppress("LeakingThis") - dependsOn(Callable { kotlinTasks.flatMap { it.dependsOn } }) + dependsOn(Callable { kotlinTasks.map { it.taskDependencies } }) } @Input @@ -82,7 +84,7 @@ open class DokkaTask : DefaultTask() { @Deprecated("Going to be removed in 0.9.16, use classpath + sourceDirs instead if kotlinTasks is not suitable for you") @Input var processConfigurations: List<Any?> = emptyList() - @Input var classpath: List<File> = arrayListOf() + @InputFiles var classpath: Iterable<File> = arrayListOf() @Input var includes: List<Any?> = arrayListOf() @@ -95,7 +97,8 @@ open class DokkaTask : DefaultTask() { @Input var sourceDirs: Iterable<File> = emptyList() - @Input var sourceRoots: MutableList<SourceRoot> = arrayListOf() + @Input + var sourceRoots: MutableList<SourceRoot> = arrayListOf() @Input var dokkaFatJar: Any = "org.jetbrains.dokka:dokka-fatjar:$version" @@ -103,7 +106,16 @@ open class DokkaTask : DefaultTask() { @Input var includeNonPublic = false @Input var skipDeprecated = false @Input var skipEmptyPackages = true - @Input var reportNotDocumented = true + + @Deprecated(`deprecationMessage reportNotDocumented`, replaceWith = ReplaceWith("reportUndocumented")) + var reportNotDocumented + get() = reportUndocumented + set(value) { + logger.warn("Dokka: reportNotDocumented is deprecated and " + `deprecationMessage reportNotDocumented`.decapitalize()) + reportUndocumented = value + } + + @Input var reportUndocumented = true @Input var perPackageOptions: MutableList<PackageOptions> = arrayListOf() @Input var impliedPlatforms: MutableList<String> = arrayListOf() @@ -111,7 +123,15 @@ open class DokkaTask : DefaultTask() { @Input var noStdlibLink: Boolean = false - @Optional @Input var cacheRoot: String? = null + @Optional @Input + var cacheRoot: String? = null + + + @Optional @Input + var languageVersion: String? = null + + @Optional @Input + var apiVersion: String? = null @get:Input internal val kotlinCompileBasedClasspathAndSourceRoots: ClasspathAndSourceRoots by lazy { extractClasspathAndSourceRootsFromKotlinTasks() } @@ -124,7 +144,7 @@ open class DokkaTask : DefaultTask() { kotlinTasksConfigurator = { closure.call() as? List<Any?> } } - fun linkMapping(closure: Closure<Any?>) { + fun linkMapping(closure: Closure<Unit>) { val mapping = LinkMapping() closure.delegate = mapping closure.call() @@ -139,21 +159,21 @@ open class DokkaTask : DefaultTask() { linkMappings.add(mapping) } - fun sourceRoot(closure: Closure<Any?>) { + fun sourceRoot(closure: Closure<Unit>) { val sourceRoot = SourceRoot() closure.delegate = sourceRoot closure.call() sourceRoots.add(sourceRoot) } - fun packageOptions(closure: Closure<Any?>) { + fun packageOptions(closure: Closure<Unit>) { val packageOptions = PackageOptions() closure.delegate = packageOptions closure.call() perPackageOptions.add(packageOptions) } - fun externalDocumentationLink(closure: Closure<Any?>) { + fun externalDocumentationLink(closure: Closure<Unit>) { val builder = DokkaConfiguration.ExternalDocumentationLink.Builder() closure.delegate = builder closure.call() @@ -269,7 +289,7 @@ open class DokkaTask : DefaultTask() { outputFormat, includeNonPublic, false, - reportNotDocumented, + reportUndocumented, skipEmptyPackages, skipDeprecated, jdkVersion, @@ -280,7 +300,9 @@ open class DokkaTask : DefaultTask() { externalDocumentationLinks, noStdlibLink, cacheRoot, - collectSuppressedFiles(sourceRoots)) + collectSuppressedFiles(sourceRoots), + languageVersion, + apiVersion) bootstrapProxy.configure( @@ -306,9 +328,7 @@ open class DokkaTask : DefaultTask() { val allConfigurations = project.configurations val fromConfigurations = - processConfigurations.map { - allConfigurations?.getByName(it.toString()) ?: throw IllegalArgumentException("No configuration $it found") - }.flatten() + processConfigurations.flatMap { allConfigurations.getByName(it.toString()) } return fromConfigurations } @@ -318,10 +338,11 @@ open class DokkaTask : DefaultTask() { logger.info("Dokka: Taking source directories provided by the user") sourceDirs.toSet() } else if (kotlinTasks.isEmpty()) { - logger.info("Dokka: Taking source directories from default java plugin") - val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java) - val sourceSets = javaPluginConvention.sourceSets?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) - sourceSets?.allSource?.srcDirs + project.convention.findPlugin(JavaPluginConvention::class.java)?.let { javaPluginConvention -> + logger.info("Dokka: Taking source directories from default java plugin") + val sourceSets = javaPluginConvention.sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME) + sourceSets?.allSource?.srcDirs + } } else { emptySet() } @@ -331,10 +352,17 @@ open class DokkaTask : DefaultTask() { @InputFiles - fun getInputFiles(): FileCollection = - project.files(collectSourceRoots().map { project.fileTree(File(it.path)) }) + - project.files(includes) + - project.files(samples.map { project.fileTree(it) }) + fun getInputFiles(): FileCollection { + val (tasksClasspath, tasksSourceRoots) = extractClasspathAndSourceRootsFromKotlinTasks() + + val fullClasspath = collectClasspathFromOldSources() + tasksClasspath + classpath + + return project.files(tasksSourceRoots.map { project.fileTree(it) }) + + project.files(collectSourceRoots().map { project.fileTree(File(it.path)) }) + + project.files(fullClasspath.map { project.fileTree(it) }) + + project.files(includes) + + project.files(samples.filterNotNull().map { project.fileTree(it) }) + } @OutputDirectory fun getOutputDirectoryAsFile(): File = project.file(outputDirectory) @@ -351,7 +379,7 @@ open class DokkaTask : DefaultTask() { } } -class SourceRoot : DokkaConfiguration.SourceRoot { +class SourceRoot : DokkaConfiguration.SourceRoot, Serializable { override var path: String = "" set(value) { field = File(value).absolutePath @@ -414,4 +442,5 @@ class PackageOptions : Serializable, DokkaConfiguration.PackageOptions { override var includeNonPublic: Boolean = false override var reportUndocumented: Boolean = true override var skipDeprecated: Boolean = false + override var suppress: Boolean = false } diff --git a/runners/maven-plugin/build.gradle b/runners/maven-plugin/build.gradle index bac05b2b..f3b9e79c 100644 --- a/runners/maven-plugin/build.gradle +++ b/runners/maven-plugin/build.gradle @@ -1,12 +1,22 @@ -import groovy.xml.QName +import groovy.io.FileType +import org.jetbrains.CorrectShadowPublishing import org.jetbrains.CrossPlatformExec +import java.nio.file.Files +import java.nio.file.StandardCopyOption + apply plugin: 'kotlin' apply plugin: 'com.github.johnrengelman.shadow' +sourceCompatibility = 1.8 -tasks.withType(AbstractCompile) { - classpath += configurations.shadow +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + freeCompilerArgs += "-Xjsr305=strict" + languageVersion = "1.2" + apiVersion = languageVersion + jvmTarget = "1.8" + } } dependencies { @@ -20,22 +30,45 @@ dependencies { shadow "org.apache.maven.plugin-tools:maven-plugin-annotations:$maven_plugin_tools_version" } -task ("generatePom") doLast { - final pomTemplate = new File(projectDir, "pom.tpl.xml") - final pom = new File(buildDir, "pom.xml") - pom.text = pomTemplate.text.replace("<version>dokka_version</version>", "<version>$dokka_version</version>") - .replace("<maven.version></maven.version>", "<maven.version>$maven_version</maven.version>") - .replace("<version>maven-plugin-plugin</version>", "<version>$maven_plugin_tools_version</version>") +task generatePom() { + inputs.file(new File(projectDir, "pom.tpl.xml")) + outputs.file(new File(buildDir, "pom.xml")) + doLast { + final pomTemplate = new File(projectDir, "pom.tpl.xml") + final pom = new File(buildDir, "pom.xml") + pom.text = pomTemplate.text.replace("<version>dokka_version</version>", "<version>$dokka_version</version>") + .replace("<maven.version></maven.version>", "<maven.version>$maven_version</maven.version>") + .replace("<version>maven-plugin-plugin</version>", "<version>$maven_plugin_tools_version</version>") + } +} + +task mergeClassOutputs doLast { + def sourceDir = new File(buildDir, "classes/kotlin") + def targetDir = new File(buildDir, "classes/java") + + sourceDir.eachFileRecurse FileType.ANY, { + def filePath = it.toPath() + def targetFilePath = targetDir.toPath().resolve(sourceDir.toPath().relativize(filePath)) + if (it.isFile()) { + Files.move(filePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING) + } else if (it.isDirectory()) { + targetFilePath.toFile().mkdirs() + } + } } task pluginDescriptor(type: CrossPlatformExec) { workingDir buildDir commandLine mvn, '-e', '-B', 'org.apache.maven.plugins:maven-plugin-plugin:descriptor' + + dependsOn mergeClassOutputs } task helpMojo(type: CrossPlatformExec) { workingDir buildDir commandLine mvn, '-e', '-B', 'org.apache.maven.plugins:maven-plugin-plugin:helpmojo' + + dependsOn mergeClassOutputs } helpMojo.dependsOn generatePom @@ -60,13 +93,15 @@ apply plugin: 'maven-publish' publishing { publications { - dokkaMavenPlugin(MavenPublication) { publication -> + dokkaMavenPlugin(MavenPublication) { MavenPublication publication -> artifactId = 'dokka-maven-plugin' artifact sourceJar { classifier "sources" } + CorrectShadowPublishing.configure(publication, project) + pom.withXml { Node root = asNode() @@ -81,7 +116,7 @@ publishing { ''') root.children().find { - return ((QName) it.name()).qualifiedName == "dependencies" + return it.name() == "dependencies" }.append(dependency) def profiles = new XmlParser().parseText(''' @@ -115,15 +150,9 @@ publishing { root.append(profiles) } - project.shadow.component(publication) - } - } -} - -tasks.withType(GenerateMavenPom) { Task generatePom -> - generatePom.doLast { + } } } -bintrayPublication(project, ['dokkaMavenPlugin'])
\ No newline at end of file +bintrayPublication(project, ['dokkaMavenPlugin']) diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index 345de523..09da90c6 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -50,6 +50,8 @@ abstract class AbstractDokkaMojo : AbstractMojo() { override var reportUndocumented: Boolean = true @Parameter override var skipDeprecated: Boolean = false + @Parameter + override var suppress: Boolean = false } @Parameter(required = true, defaultValue = "\${project.compileSourceRoots}") @@ -105,6 +107,12 @@ abstract class AbstractDokkaMojo : AbstractMojo() { @Parameter var cacheRoot: String? = null + @Parameter + var languageVersion: String? = null + + @Parameter + var apiVersion: String? = null + protected abstract fun getOutDir(): String protected abstract fun getOutFormat(): String @@ -131,7 +139,9 @@ abstract class AbstractDokkaMojo : AbstractMojo() { perPackageOptions = perPackageOptions, externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, noStdlibLink = noStdlibLink, - cacheRoot = cacheRoot + cacheRoot = cacheRoot, + languageVersion = languageVersion, + apiVersion = apiVersion ) ) |