From 7acc52ba723eab08fe796fcfd68755e7f0eb6a66 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 00:50:08 +0300 Subject: WIP: Refactoring, remove LocationService, rework FormatDescriptor --- core/src/main/kotlin/Utilities/DokkaModules.kt | 46 ++++++++++++-------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index dfb114ec..9db08010 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -4,6 +4,7 @@ import com.google.inject.Binder import com.google.inject.Module import com.google.inject.Provider import com.google.inject.TypeLiteral +import com.google.inject.binder.AnnotatedBindingBuilder import com.google.inject.name.Names import org.jetbrains.dokka.* import org.jetbrains.dokka.Formats.FormatDescriptor @@ -11,6 +12,7 @@ import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.dokka.Samples.SampleProcessingService import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import java.io.File +import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" @@ -22,12 +24,7 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, override fun configure(binder: Binder) { binder.bind().toInstance(logger) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) - binder.bind().to(descriptor.descriptorSignatureProvider.java) binder.registerCategory("language") - binder.bind().to(descriptor.packageDocumentationBuilderClass.java) - binder.bind().to(descriptor.javaDocumentationBuilderClass.java) - binder.bind().to(descriptor.sampleProcessingService.java) val coreEnvironment = environment.createCoreEnvironment() binder.bind().toInstance(coreEnvironment) @@ -40,6 +37,9 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(defaultPlatformsProvider) binder.bind().toInstance(nodeReferenceGraph) + + val descriptor = ServiceLocator.lookup("format", options.outputFormat) + descriptor.configureAnalysis(binder) } } @@ -56,35 +56,26 @@ class DokkaOutputModule(val options: DocumentationOptions, binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) - binder.bindNameAnnotated("singleFolder") - binder.bindNameAnnotated("singleFolder") - binder.bindNameAnnotated("folders") - binder.bindNameAnnotated("folders") +// binder.bindNameAnnotated("singleFolder") +// binder.bindNameAnnotated("singleFolder") +// binder.bindNameAnnotated("folders") +// binder.bindNameAnnotated("folders") // defaults - binder.bind(LocationService::class.java).to(FoldersLocationService::class.java) - binder.bind(FileLocationService::class.java).to(FoldersLocationService::class.java) +// binder.bind(LocationService::class.java).to(FoldersLocationService::class.java) +// binder.bind(FileLocationService::class.java).to(FoldersLocationService::class.java) binder.registerCategory("outline") binder.registerCategory("format") binder.registerCategory("generator") - val descriptor = ServiceLocator.lookup("format", options.outputFormat) - - descriptor.outlineServiceClass?.let { clazz -> - binder.bind(OutlineFormatService::class.java).to(clazz.java) - } - descriptor.formatServiceClass?.let { clazz -> - binder.bind(FormatService::class.java).to(clazz.java) - } - - binder.bind().to(descriptor.generatorServiceClass.java) - - descriptor.packageListServiceClass?.let { binder.bind().to(it.java) } - binder.bind().toInstance(options) binder.bind().toInstance(logger) binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(options.impliedPlatforms) + + val descriptor = ServiceLocator.lookup("format", options.outputFormat) + + descriptor.configureOutput(binder) } } @@ -100,4 +91,9 @@ private inline fun Binder.bindNameAnnotat } -inline fun Binder.bind() = bind(T::class.java) +inline fun Binder.bind(): AnnotatedBindingBuilder = bind(T::class.java) + +inline infix fun > AnnotatedBindingBuilder.toOptional(kClass: TKClass?) = + kClass?.let { to(it.java) } + +inline infix fun > AnnotatedBindingBuilder.toType(kClass: TKClass) = to(kClass.java) -- cgit From c1abcaf32abd4e2d74b9246385b3541096cdb5b9 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 04:29:07 +0300 Subject: Extract Analysis components out of FormatDescriptor Fight with statically injected HtmlTemplateService --- core/src/main/kotlin/Formats/AnalysisComponents.kt | 45 ++++++++++++++++++++++ core/src/main/kotlin/Formats/FormatDescriptor.kt | 25 ++++-------- .../Formats/KotlinWebsiteHtmlFormatService.kt | 14 ++++--- core/src/main/kotlin/Formats/StandardFormats.kt | 42 ++++++++++---------- core/src/main/kotlin/Utilities/DokkaModules.kt | 5 --- core/src/main/kotlin/javadoc/dokka-adapters.kt | 13 ++----- 6 files changed, 84 insertions(+), 60 deletions(-) create mode 100644 core/src/main/kotlin/Formats/AnalysisComponents.kt (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Formats/AnalysisComponents.kt b/core/src/main/kotlin/Formats/AnalysisComponents.kt new file mode 100644 index 00000000..97e1311e --- /dev/null +++ b/core/src/main/kotlin/Formats/AnalysisComponents.kt @@ -0,0 +1,45 @@ +package org.jetbrains.dokka.Formats + +import com.google.inject.Binder +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.SampleProcessingService +import org.jetbrains.dokka.Utilities.bind +import org.jetbrains.dokka.Utilities.toType +import kotlin.reflect.KClass + + +interface FormatDescriptorAnalysisComponentProvider : FormatDescriptorAnalysisComponent { + + val packageDocumentationBuilderClass: KClass + val javaDocumentationBuilderClass: KClass + val sampleProcessingService: KClass + val descriptorSignatureProvider: KClass + + + override fun configureAnalysis(binder: Binder): Unit = with(binder) { + bind() toType descriptorSignatureProvider + bind() toType packageDocumentationBuilderClass + bind() toType javaDocumentationBuilderClass + bind() toType sampleProcessingService + } +} + + +object KotlinAsJava: FormatDescriptorAnalysisComponentProvider { + override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class + override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class + override val sampleProcessingService = DefaultSampleProcessingService::class + override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class +} + + +object KotlinAsKotlin: FormatDescriptorAnalysisComponentProvider { + override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class + override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class + override val sampleProcessingService = DefaultSampleProcessingService::class + override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class +} \ No newline at end of file diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt index fc0c4417..d3861b82 100644 --- a/core/src/main/kotlin/Formats/FormatDescriptor.kt +++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt @@ -9,33 +9,24 @@ import org.jetbrains.dokka.Utilities.toOptional import org.jetbrains.dokka.Utilities.toType import kotlin.reflect.KClass -interface FormatDescriptor { + +interface FormatDescriptorAnalysisComponent { fun configureAnalysis(binder: Binder) - fun configureOutput(binder: Binder) } -interface FormatDescriptorAnalysisComponentProvider : FormatDescriptor { - - val packageDocumentationBuilderClass: KClass - val javaDocumentationBuilderClass: KClass - val sampleProcessingService: KClass - val descriptorSignatureProvider: KClass +interface FormatDescriptorOutputComponent { + fun configureOutput(binder: Binder) +} +interface FormatDescriptor: FormatDescriptorAnalysisComponent, FormatDescriptorOutputComponent - override fun configureAnalysis(binder: Binder): Unit = with(binder) { - bind() toType descriptorSignatureProvider - bind() toType packageDocumentationBuilderClass - bind() toType javaDocumentationBuilderClass - bind() toType sampleProcessingService - } -} -abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor, FormatDescriptorAnalysisComponentProvider { +abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor { override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toOptional (outlineServiceClass) bind() toOptional formatServiceClass - bind() toType generatorServiceClass + bind() toType generatorServiceClass //bind() toType generatorServiceClass bind() toOptional packageListServiceClass } diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 8fd53cdd..208756c8 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -7,7 +7,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import java.nio.file.Path -private object EmptyHtmlTemplateService : HtmlTemplateService { +object EmptyHtmlTemplateService : HtmlTemplateService { override fun appendFooter(to: StringBuilder) {} override fun appendHeader(to: StringBuilder, title: String?, basePath: Path) {} @@ -20,8 +20,9 @@ open class KotlinWebsiteHtmlOutputBuilder( generator: NodeLocationAwareGenerator, languageService: LanguageService, extension: String, - impliedPlatforms: List -) : HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, EmptyHtmlTemplateService) { + impliedPlatforms: List, + templateService: HtmlTemplateService +) : HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) { private var needHardLineBreaks = false private var insideDiv = 0 @@ -173,12 +174,13 @@ open class KotlinWebsiteHtmlOutputBuilder( class KotlinWebsiteHtmlFormatService @Inject constructor( generator: NodeLocationAwareGenerator, signatureGenerator: LanguageService, - @Named(impliedPlatformsName) impliedPlatforms: List -) : HtmlFormatService(generator, signatureGenerator, EmptyHtmlTemplateService, impliedPlatforms) { + @Named(impliedPlatformsName) impliedPlatforms: List, + templateService: HtmlTemplateService +) : HtmlFormatService(generator, signatureGenerator, templateService, impliedPlatforms) { override fun enumerateSupportFiles(callback: (String, String) -> Unit) {} override fun createOutputBuilder(to: StringBuilder, location: Location) = - KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) + KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) } diff --git a/core/src/main/kotlin/Formats/StandardFormats.kt b/core/src/main/kotlin/Formats/StandardFormats.kt index 54544ebc..9de667ab 100644 --- a/core/src/main/kotlin/Formats/StandardFormats.kt +++ b/core/src/main/kotlin/Formats/StandardFormats.kt @@ -1,41 +1,34 @@ package org.jetbrains.dokka.Formats +import com.google.inject.Binder +import com.google.inject.Provider import org.jetbrains.dokka.* -import org.jetbrains.dokka.Kotlin.KotlinAsJavaDescriptorSignatureProvider -import org.jetbrains.dokka.Kotlin.KotlinDescriptorSignatureProvider -import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import org.jetbrains.dokka.Samples.KotlinWebsiteSampleProcessingService -import org.jetbrains.dokka.Samples.SampleProcessingService +import org.jetbrains.dokka.Utilities.bind import kotlin.reflect.KClass -abstract class KotlinFormatDescriptorBase : FileGeneratorBasedFormatDescriptor() { - - override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class - override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class - +abstract class KotlinFormatDescriptorBase : FileGeneratorBasedFormatDescriptor(), FormatDescriptorAnalysisComponentProvider by KotlinAsKotlin { override val generatorServiceClass = FileGenerator::class override val outlineServiceClass: KClass? = null - override val sampleProcessingService: KClass = DefaultSampleProcessingService::class override val packageListServiceClass: KClass? = DefaultPackageListService::class - override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class -} - -class HtmlFormatDescriptor : KotlinFormatDescriptorBase() { - override val formatServiceClass = HtmlFormatService::class - override val outlineServiceClass = HtmlFormatService::class } -class HtmlAsJavaFormatDescriptor : FileGeneratorBasedFormatDescriptor() { +abstract class HtmlFormatDescriptorBase : FileGeneratorBasedFormatDescriptor() { override val formatServiceClass = HtmlFormatService::class override val outlineServiceClass = HtmlFormatService::class override val generatorServiceClass = FileGenerator::class - override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class - override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class - override val sampleProcessingService: KClass = DefaultSampleProcessingService::class - override val packageListServiceClass: KClass? = DefaultPackageListService::class - override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class + override val packageListServiceClass = DefaultPackageListService::class + + override fun configureOutput(binder: Binder): Unit = with(binder) { + super.configureOutput(binder) + bind().toProvider(Provider { HtmlTemplateService.default("style.css") }) + } } +class HtmlFormatDescriptor : HtmlFormatDescriptorBase(), FormatDescriptorAnalysisComponent by KotlinAsKotlin + +class HtmlAsJavaFormatDescriptor : HtmlFormatDescriptorBase(), FormatDescriptorAnalysisComponent by KotlinAsJava + class KotlinWebsiteFormatDescriptor : KotlinFormatDescriptorBase() { override val formatServiceClass = KotlinWebsiteFormatService::class override val outlineServiceClass = YamlOutlineService::class @@ -51,6 +44,11 @@ class KotlinWebsiteHtmlFormatDescriptor : KotlinFormatDescriptorBase() { override val formatServiceClass = KotlinWebsiteHtmlFormatService::class override val sampleProcessingService = KotlinWebsiteSampleProcessingService::class override val outlineServiceClass = YamlOutlineService::class + + override fun configureOutput(binder: Binder) = with(binder) { + super.configureOutput(binder) + bind().toInstance(EmptyHtmlTemplateService) + } } class JekyllFormatDescriptor : KotlinFormatDescriptorBase() { diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 9db08010..a2d720ef 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -49,11 +49,6 @@ class DokkaOutputModule(val options: DocumentationOptions, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { binder.bind(LanguageService::class.java).to(KotlinLanguageService::class.java) - - binder.bind(HtmlTemplateService::class.java).toProvider(object : Provider { - override fun get(): HtmlTemplateService = HtmlTemplateService.default("style.css") - }) - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) // binder.bindNameAnnotated("singleFolder") diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt index 84dff8f0..bed211f6 100644 --- a/core/src/main/kotlin/javadoc/dokka-adapters.kt +++ b/core/src/main/kotlin/javadoc/dokka-adapters.kt @@ -5,13 +5,10 @@ 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.Formats.FormatDescriptorAnalysisComponentProvider -import org.jetbrains.dokka.Kotlin.KotlinAsJavaDescriptorSignatureProvider -import org.jetbrains.dokka.Model.DescriptorSignatureProvider -import org.jetbrains.dokka.Samples.DefaultSampleProcessingService +import org.jetbrains.dokka.Formats.FormatDescriptorAnalysisComponent +import org.jetbrains.dokka.Formats.KotlinAsJava import org.jetbrains.dokka.Utilities.bind import org.jetbrains.dokka.Utilities.toType -import kotlin.reflect.KClass class JavadocGenerator @Inject constructor(val options: DocumentationOptions, val logger: DokkaLogger) : Generator { @@ -34,11 +31,7 @@ class JavadocGenerator @Inject constructor(val options: DocumentationOptions, va } } -class JavadocFormatDescriptor : FormatDescriptor, FormatDescriptorAnalysisComponentProvider { - override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class - override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class - override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class +class JavadocFormatDescriptor : FormatDescriptor, FormatDescriptorAnalysisComponent by KotlinAsJava { override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toType JavadocGenerator::class -- cgit From 1eab9404b8ecbd51e5270af0cc0c9545e68f35f2 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 05:20:21 +0300 Subject: Remove categories to prevent injection errors When not NodeLocationAwareGenerator used --- core/src/main/kotlin/Utilities/DokkaModules.kt | 13 ------------- core/src/main/resources/dokka/generator/default.properties | 2 -- core/src/main/resources/dokka/generator/javadoc.properties | 2 -- core/src/main/resources/dokka/language/java.properties | 1 - core/src/main/resources/dokka/language/kotlin.properties | 1 - core/src/main/resources/dokka/outline/yaml.properties | 1 - 6 files changed, 20 deletions(-) delete mode 100644 core/src/main/resources/dokka/generator/default.properties delete mode 100644 core/src/main/resources/dokka/generator/javadoc.properties delete mode 100644 core/src/main/resources/dokka/language/java.properties delete mode 100644 core/src/main/resources/dokka/language/kotlin.properties delete mode 100644 core/src/main/resources/dokka/outline/yaml.properties (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index a2d720ef..fcc2f692 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -51,19 +51,6 @@ class DokkaOutputModule(val options: DocumentationOptions, binder.bind(LanguageService::class.java).to(KotlinLanguageService::class.java) binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) -// binder.bindNameAnnotated("singleFolder") -// binder.bindNameAnnotated("singleFolder") -// binder.bindNameAnnotated("folders") -// binder.bindNameAnnotated("folders") - - // defaults -// binder.bind(LocationService::class.java).to(FoldersLocationService::class.java) -// binder.bind(FileLocationService::class.java).to(FoldersLocationService::class.java) - - binder.registerCategory("outline") - binder.registerCategory("format") - binder.registerCategory("generator") - binder.bind().toInstance(options) binder.bind().toInstance(logger) binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(options.impliedPlatforms) diff --git a/core/src/main/resources/dokka/generator/default.properties b/core/src/main/resources/dokka/generator/default.properties deleted file mode 100644 index a4a16200..00000000 --- a/core/src/main/resources/dokka/generator/default.properties +++ /dev/null @@ -1,2 +0,0 @@ -class=org.jetbrains.dokka.FileGenerator -description=Default documentation generator \ No newline at end of file diff --git a/core/src/main/resources/dokka/generator/javadoc.properties b/core/src/main/resources/dokka/generator/javadoc.properties deleted file mode 100644 index 4075704f..00000000 --- a/core/src/main/resources/dokka/generator/javadoc.properties +++ /dev/null @@ -1,2 +0,0 @@ -class=org.jetbrains.dokka.javadoc.JavadocGenerator -description=Produces output via JDK javadoc tool \ No newline at end of file diff --git a/core/src/main/resources/dokka/language/java.properties b/core/src/main/resources/dokka/language/java.properties deleted file mode 100644 index ab42f532..00000000 --- a/core/src/main/resources/dokka/language/java.properties +++ /dev/null @@ -1 +0,0 @@ -class=org.jetbrains.dokka.JavaLanguageService \ No newline at end of file diff --git a/core/src/main/resources/dokka/language/kotlin.properties b/core/src/main/resources/dokka/language/kotlin.properties deleted file mode 100644 index 16092007..00000000 --- a/core/src/main/resources/dokka/language/kotlin.properties +++ /dev/null @@ -1 +0,0 @@ -class=org.jetbrains.dokka.KotlinLanguageService \ No newline at end of file diff --git a/core/src/main/resources/dokka/outline/yaml.properties b/core/src/main/resources/dokka/outline/yaml.properties deleted file mode 100644 index 7268af37..00000000 --- a/core/src/main/resources/dokka/outline/yaml.properties +++ /dev/null @@ -1 +0,0 @@ -class=org.jetbrains.dokka.YamlOutlineService \ No newline at end of file -- cgit From 214e16e07d93b3565c433ed67b78796e80f43ec5 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 5 Dec 2017 18:25:08 +0300 Subject: Tidy around --- core/src/main/kotlin/Formats/StandardFormats.kt | 4 - .../kotlin/Locations/FoldersLocationService.kt | 20 ---- core/src/main/kotlin/Locations/Location.kt | 59 ++++++++++++ core/src/main/kotlin/Locations/LocationService.kt | 104 --------------------- .../Locations/SingleFolderLocationService.kt | 20 ---- core/src/main/kotlin/Utilities/DokkaModules.kt | 2 - 6 files changed, 59 insertions(+), 150 deletions(-) delete mode 100644 core/src/main/kotlin/Locations/FoldersLocationService.kt create mode 100644 core/src/main/kotlin/Locations/Location.kt delete mode 100644 core/src/main/kotlin/Locations/LocationService.kt delete mode 100644 core/src/main/kotlin/Locations/SingleFolderLocationService.kt (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Formats/StandardFormats.kt b/core/src/main/kotlin/Formats/StandardFormats.kt index 71af1991..dd67ac97 100644 --- a/core/src/main/kotlin/Formats/StandardFormats.kt +++ b/core/src/main/kotlin/Formats/StandardFormats.kt @@ -47,10 +47,6 @@ class KotlinWebsiteHtmlFormatDescriptor : KotlinFormatDescriptorBase() { override val sampleProcessingService = KotlinWebsiteSampleProcessingService::class override val outlineServiceClass = YamlOutlineService::class - override fun configureAnalysis(binder: Binder) { - super.configureAnalysis(binder) - } - override fun configureOutput(binder: Binder) = with(binder) { super.configureOutput(binder) bind().toInstance(EmptyHtmlTemplateService) diff --git a/core/src/main/kotlin/Locations/FoldersLocationService.kt b/core/src/main/kotlin/Locations/FoldersLocationService.kt deleted file mode 100644 index ae5301e7..00000000 --- a/core/src/main/kotlin/Locations/FoldersLocationService.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.jetbrains.dokka - -import com.google.inject.Inject -import com.google.inject.name.Named -import java.io.File -// -//class FoldersLocationService @Inject constructor(@Named("outputDir") val rootFile: File, val extension: String) : FileLocationService { -// constructor(root: String): this(File(root), "") -// -// override val root: Location -// get() = FileLocation(rootFile) -// -// override fun withExtension(newExtension: String): FileLocationService { -// return if (extension.isEmpty()) FoldersLocationService(rootFile, newExtension) else this -// } -// -// override fun location(qualifiedName: List, hasMembers: Boolean): FileLocation { -// return FileLocation(File(rootFile, relativePathToNode(qualifiedName, hasMembers)).appendExtension(extension)) -// } -//} diff --git a/core/src/main/kotlin/Locations/Location.kt b/core/src/main/kotlin/Locations/Location.kt new file mode 100644 index 00000000..17538ff5 --- /dev/null +++ b/core/src/main/kotlin/Locations/Location.kt @@ -0,0 +1,59 @@ +package org.jetbrains.dokka + +import java.io.File + +interface Location { + val path: String get + fun relativePathTo(other: Location, anchor: String? = null): String +} + +/** + * Represents locations in the documentation in the form of [path](File). + * + * $file: [File] for this location + * $path: [String] representing path of this location + */ +data class FileLocation(val file: File): Location { + override val path : String + get() = file.path + + override fun relativePathTo(other: Location, anchor: String?): String { + if (other !is FileLocation) { + throw IllegalArgumentException("$other is not a FileLocation") + } + if (file.path.substringBeforeLast(".") == other.file.path.substringBeforeLast(".") && anchor == null) { + return "./${file.name}" + } + val ownerFolder = file.parentFile!! + val relativePath = ownerFolder.toPath().relativize(other.file.toPath()).toString().replace(File.separatorChar, '/') + return if (anchor == null) relativePath else relativePath + "#" + anchor + } +} + + +fun relativePathToNode(qualifiedName: List, hasMembers: Boolean): String { + val parts = qualifiedName.map { identifierToFilename(it) }.filterNot { it.isEmpty() } + return if (!hasMembers) { + // leaf node, use file in owner's folder + parts.joinToString("/") + } else { + parts.joinToString("/") + (if (parts.none()) "" else "/") + "index" + } +} + +fun relativePathToNode(node: DocumentationNode) = relativePathToNode(node.path.map { it.name }, node.members.any()) + +fun identifierToFilename(path: String): String { + val escaped = path.replace('<', '-').replace('>', '-') + val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() } + return if (lowercase == "index") "--index--" else lowercase +} + +fun NodeLocationAwareGenerator.relativePathToLocation(owner: DocumentationNode, node: DocumentationNode): String { + return location(owner).relativePathTo(location(node), null) +} + +fun NodeLocationAwareGenerator.relativeToRoot(from: Location): File { + val file = File(from.path) + return file.relativeTo(root) +} \ No newline at end of file diff --git a/core/src/main/kotlin/Locations/LocationService.kt b/core/src/main/kotlin/Locations/LocationService.kt deleted file mode 100644 index e453baca..00000000 --- a/core/src/main/kotlin/Locations/LocationService.kt +++ /dev/null @@ -1,104 +0,0 @@ -package org.jetbrains.dokka - -import java.io.File - -interface Location { - val path: String get - fun relativePathTo(other: Location, anchor: String? = null): String -} - -/** - * Represents locations in the documentation in the form of [path](File). - * - * Locations are provided by [LocationService.location] function. - * - * $file: [File] for this location - * $path: [String] representing path of this location - */ -data class FileLocation(val file: File): Location { - override val path : String - get() = file.path - - override fun relativePathTo(other: Location, anchor: String?): String { - if (other !is FileLocation) { - throw IllegalArgumentException("$other is not a FileLocation") - } - if (file.path.substringBeforeLast(".") == other.file.path.substringBeforeLast(".") && anchor == null) { - return "./${file.name}" - } - val ownerFolder = file.parentFile!! - val relativePath = ownerFolder.toPath().relativize(other.file.toPath()).toString().replace(File.separatorChar, '/') - return if (anchor == null) relativePath else relativePath + "#" + anchor - } -} - - - -fun relativePathToNode(qualifiedName: List, hasMembers: Boolean): String { - val parts = qualifiedName.map { identifierToFilename(it) }.filterNot { it.isEmpty() } - return if (!hasMembers) { - // leaf node, use file in owner's folder - parts.joinToString("/") - } else { - parts.joinToString("/") + (if (parts.none()) "" else "/") + "index" - } -} - -fun relativePathToNode(node: DocumentationNode) = relativePathToNode(node.path.map { it.name }, node.members.any()) - - -// -///** -// * Provides means of retrieving locations for [DocumentationNode](documentation nodes) -// * -// * `LocationService` determines where documentation for particular node should be generated -// * -// * * [FoldersLocationService] – represent packages and types as folders, members as files in those folders. -// * * [SingleFolderLocationService] – all documentation is generated into single folder using fully qualified names -// * for file names. -// */ -//interface LocationService { -// fun withExtension(newExtension: String) = this -// -// fun location(node: DocumentationNode): Location = location(node.path.map { it.name }, node.members.any()) -// -// /** -// * Calculates a location corresponding to the specified [qualifiedName]. -// * @param hasMembers if true, the node for which the location is calculated has member nodes. -// */ -// fun location(qualifiedName: List, hasMembers: Boolean): Location -// -// val root: Location -//} -// -// -//interface FileLocationService: LocationService { -// override fun withExtension(newExtension: String): FileLocationService = this -// -// override fun location(node: DocumentationNode): FileLocation = location(node.path.map { it.name }, node.members.any()) -// override fun location(qualifiedName: List, hasMembers: Boolean): FileLocation -//} - -fun identifierToFilename(path: String): String { - val escaped = path.replace('<', '-').replace('>', '-') - val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() } - return if (lowercase == "index") "--index--" else lowercase -} - -///** -// * Returns relative location between two nodes. Used for relative links in documentation. -// */ -//fun LocationService.relativePathToLocation(owner: DocumentationNode, node: DocumentationNode): String { -// return location(owner).relativePathTo(location(node), null) -//} - - -fun NodeLocationAwareGenerator.relativePathToLocation(owner: DocumentationNode, node: DocumentationNode): String { - return location(owner).relativePathTo(location(node), null) -} - - -fun NodeLocationAwareGenerator.relativeToRoot(from: Location): File { - val file = File(from.path) - return file.relativeTo(root) -} \ No newline at end of file diff --git a/core/src/main/kotlin/Locations/SingleFolderLocationService.kt b/core/src/main/kotlin/Locations/SingleFolderLocationService.kt deleted file mode 100644 index 25cf6f8e..00000000 --- a/core/src/main/kotlin/Locations/SingleFolderLocationService.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.jetbrains.dokka - -import com.google.inject.Inject -import com.google.inject.name.Named -import java.io.File -// -//class SingleFolderLocationService @Inject constructor(@Named("outputDir") val rootFile: File, val extension: String) : FileLocationService { -// constructor(root: String): this(File(root), "") -// -// override fun withExtension(newExtension: String): FileLocationService = -// SingleFolderLocationService(rootFile, newExtension) -// -// override fun location(qualifiedName: List, hasMembers: Boolean): FileLocation { -// val filename = qualifiedName.map { identifierToFilename(it) }.joinToString("-") -// return FileLocation(File(rootFile, filename).appendExtension(extension)) -// } -// -// override val root: Location -// get() = FileLocation(rootFile) -//} \ No newline at end of file diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index fcc2f692..6b5e153e 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -24,8 +24,6 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, override fun configure(binder: Binder) { binder.bind().toInstance(logger) - binder.registerCategory("language") - val coreEnvironment = environment.createCoreEnvironment() binder.bind().toInstance(coreEnvironment) -- cgit From 6ef35accd16533c84be5d0164739b146cfb55b73 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 11 Dec 2017 16:01:51 +0300 Subject: Fix optional binding --- core/src/main/kotlin/Formats/FormatDescriptor.kt | 10 ++++++---- core/src/main/kotlin/Utilities/DokkaModules.kt | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt index aa00df97..a1120c00 100644 --- a/core/src/main/kotlin/Formats/FormatDescriptor.kt +++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt @@ -3,6 +3,7 @@ package org.jetbrains.dokka.Formats import com.google.inject.Binder import org.jetbrains.dokka.* import org.jetbrains.dokka.Utilities.bind +import org.jetbrains.dokka.Utilities.lazyBind import org.jetbrains.dokka.Utilities.toOptional import org.jetbrains.dokka.Utilities.toType import kotlin.reflect.KClass @@ -23,11 +24,12 @@ abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor { override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toType NodeLocationAwareGenerator::class - - bind() toOptional (outlineServiceClass) - bind() toOptional formatServiceClass bind() toType generatorServiceClass - bind() toOptional packageListServiceClass + + + lazyBind() toOptional (outlineServiceClass) + lazyBind() toOptional formatServiceClass + lazyBind() toOptional packageListServiceClass } abstract val formatServiceClass: KClass? diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 6b5e153e..763e29a9 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -73,7 +73,9 @@ private inline fun Binder.bindNameAnnotat inline fun Binder.bind(): AnnotatedBindingBuilder = bind(T::class.java) -inline infix fun > AnnotatedBindingBuilder.toOptional(kClass: TKClass?) = - kClass?.let { to(it.java) } +inline fun Binder.lazyBind(): Lazy> = lazy { bind(T::class.java) } + +inline infix fun > Lazy>.toOptional(kClass: TKClass?) = + kClass?.let { value toType it } inline infix fun > AnnotatedBindingBuilder.toType(kClass: TKClass) = to(kClass.java) -- cgit From ec3d364e49268f1dfbc7619245ec36a49e780169 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 15 Dec 2017 22:01:02 +0300 Subject: Don't force bind LanguageService to KotlinLanguageService --- core/src/main/kotlin/Utilities/DokkaModules.kt | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 763e29a9..36704918 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -46,7 +46,6 @@ object StringListType : TypeLiteral<@JvmSuppressWildcards List>() class DokkaOutputModule(val options: DocumentationOptions, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(LanguageService::class.java).to(KotlinLanguageService::class.java) binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) binder.bind().toInstance(options) -- cgit From a3f16fd75c200020465f79563ca58b2833236865 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 24 Apr 2018 20:35:42 +0300 Subject: [backport] Stabilize signatures to fix linking from Java to Kotlin Basically there is 2 ways to get signature, from PSI and from descriptors, and there should be only one way in one session Original: adc09f2 --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 3 +- .../main/kotlin/Analysis/JavaResolveExtension.kt | 131 +++++++++++++++++++++ core/src/main/kotlin/Formats/AnalysisComponents.kt | 14 +-- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 6 +- core/src/main/kotlin/Java/JavadocParser.kt | 5 +- .../main/kotlin/Kotlin/DeclarationLinkResolver.kt | 7 +- .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 6 +- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 23 ++-- .../KotlinAsJavaDescriptorSignatureProvider.kt | 22 ---- .../Kotlin/KotlinAsJavaElementSignatureProvider.kt | 25 ++++ .../Kotlin/KotlinDescriptorSignatureProvider.kt | 9 -- .../Kotlin/KotlinElementSignatureProvider.kt | 31 +++++ .../kotlin/Model/DescriptorSignatureProvider.kt | 7 -- core/src/main/kotlin/Model/DocumentationNode.kt | 7 +- .../main/kotlin/Model/ElementSignatureProvider.kt | 9 ++ core/src/main/kotlin/Utilities/DokkaModules.kt | 3 - 16 files changed, 230 insertions(+), 78 deletions(-) create mode 100644 core/src/main/kotlin/Analysis/JavaResolveExtension.kt delete mode 100644 core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt create mode 100644 core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt delete mode 100644 core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt create mode 100644 core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt delete mode 100644 core/src/main/kotlin/Model/DescriptorSignatureProvider.kt create mode 100644 core/src/main/kotlin/Model/ElementSignatureProvider.kt (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index b2e4b490..6854b323 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.index.JavaRoot import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -250,7 +251,7 @@ class DokkaResolutionFacade(override val project: Project, } override fun tryGetFrontendService(element: PsiElement, serviceClass: Class): T? { - return null + return resolverForModule.componentProvider.tryGetService(serviceClass) } override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor { diff --git a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt new file mode 100644 index 00000000..f8992d45 --- /dev/null +++ b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:JvmName("JavaResolutionUtils") + +package org.jetbrains.dokka + +import com.intellij.psi.* +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.unwrapped +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.load.java.sources.JavaSourceElement +import org.jetbrains.kotlin.load.java.structure.* +import org.jetbrains.kotlin.load.java.structure.impl.* +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.psiUtil.parameterIndex +import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope + +// TODO: Remove that file + +@JvmOverloads +fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { + val method = originalElement as? PsiMethod ?: return null + if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null + val resolver = method.getJavaDescriptorResolver(resolutionFacade) + return when { + method.isConstructor -> resolver?.resolveConstructor(JavaConstructorImpl(method)) + else -> resolver?.resolveMethod(JavaMethodImpl(method)) + } +} + +@JvmOverloads +fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? { + val psiClass = originalElement as? PsiClass ?: return null + return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass)) +} + +@JvmOverloads +fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? { + val field = originalElement as? PsiField ?: return null + return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field)) +} + +@JvmOverloads +fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { + return when (this) { + is PsiEnumConstant -> containingClass?.getJavaClassDescriptor(resolutionFacade) + is PsiClass -> getJavaClassDescriptor(resolutionFacade) + is PsiMethod -> getJavaMethodDescriptor(resolutionFacade) + is PsiField -> getJavaFieldDescriptor(resolutionFacade) + else -> null + } +} + +@JvmOverloads +fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { + val callable = unwrapped + return when (callable) { + is PsiMember -> getJavaMemberDescriptor(resolutionFacade) + is KtDeclaration -> { + val descriptor = resolutionFacade.resolveToDescriptor(callable) + if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor + } + else -> null + } +} + +private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? { + return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java) +} + +private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): DeclarationDescriptor? { + return getContainingScope(method) + ?.getContributedDescriptors(nameFilter = { true }, kindFilter = DescriptorKindFilter.CALLABLES) + ?.filterIsInstance() + ?.findByJavaElement(method) +} + +private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? { + return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor) +} + +private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? { + return getContainingScope(field)?.getContributedVariables(field.name, NoLookupLocation.FROM_IDE)?.findByJavaElement(field) +} + +private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? { + val containingClass = resolveClass(member.containingClass) + return if (member.isStatic) + containingClass?.staticScope + else + containingClass?.defaultType?.memberScope +} + +private fun Collection.findByJavaElement(javaElement: JavaElement): T? { + return firstOrNull { member -> + val memberJavaElement = (member.original.source as? JavaSourceElement)?.javaElement + when { + memberJavaElement == javaElement -> + true + memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> -> + memberJavaElement.psi.isEquivalentTo(javaElement.psi) + else -> + false + } + } +} + +fun PsiElement.javaResolutionFacade() = + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform) diff --git a/core/src/main/kotlin/Formats/AnalysisComponents.kt b/core/src/main/kotlin/Formats/AnalysisComponents.kt index c4d97dbb..d78d4a0c 100644 --- a/core/src/main/kotlin/Formats/AnalysisComponents.kt +++ b/core/src/main/kotlin/Formats/AnalysisComponents.kt @@ -2,9 +2,9 @@ package org.jetbrains.dokka.Formats import com.google.inject.Binder 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.KotlinAsJavaElementSignatureProvider +import org.jetbrains.dokka.KotlinElementSignatureProvider +import org.jetbrains.dokka.ElementSignatureProvider import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import org.jetbrains.dokka.Samples.SampleProcessingService import org.jetbrains.dokka.Utilities.bind @@ -16,12 +16,12 @@ interface DefaultAnalysisComponentServices { val packageDocumentationBuilderClass: KClass val javaDocumentationBuilderClass: KClass val sampleProcessingService: KClass - val descriptorSignatureProvider: KClass + val elementSignatureProvider: KClass } interface DefaultAnalysisComponent : FormatDescriptorAnalysisComponent, DefaultAnalysisComponentServices { override fun configureAnalysis(binder: Binder): Unit = with(binder) { - bind() toType descriptorSignatureProvider + bind() toType elementSignatureProvider bind() toType packageDocumentationBuilderClass bind() toType javaDocumentationBuilderClass bind() toType sampleProcessingService @@ -33,7 +33,7 @@ object KotlinAsJava : DefaultAnalysisComponentServices { override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class + override val elementSignatureProvider = KotlinAsJavaElementSignatureProvider::class } @@ -41,5 +41,5 @@ object KotlinAsKotlin : DefaultAnalysisComponentServices { override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class + override val elementSignatureProvider = KotlinElementSignatureProvider::class } \ 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 cf2b0514..646096e5 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -45,10 +45,10 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser - @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger) { + @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger, signatureProvider: ElementSignatureProvider) { this.options = options this.refGraph = refGraph - this.docParser = JavadocParser(refGraph, logger) + this.docParser = JavadocParser(refGraph, logger, signatureProvider) } constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { @@ -61,7 +61,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { if (skipFile(file) || file.classes.all { skipElement(it) }) { return } - val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap(), refGraph) + val packageNode = findOrCreatePackageNode(module, file.packageName, emptyMap(), refGraph) appendClasses(packageNode, file.classes) } diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index db61a00a..365ae298 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -22,7 +22,8 @@ interface JavaDocumentationParser { class JavadocParser( private val refGraph: NodeReferenceGraph, - private val logger: DokkaLogger + private val logger: DokkaLogger, + private val signatureProvider: ElementSignatureProvider ) : JavaDocumentationParser { override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult { val docComment = (element as? PsiDocCommentOwner)?.docComment @@ -157,7 +158,7 @@ class JavadocParser( private fun resolveLink(valueElement: PsiElement?): String? { val target = valueElement?.reference?.resolve() if (target != null) { - return getSignature(target) + return signatureProvider.signature(target) } return null } diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index ec474900..d73bef4a 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -1,13 +1,10 @@ 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, @@ -15,7 +12,7 @@ class DeclarationLinkResolver val logger: DokkaLogger, val options: DocumentationOptions, val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver, - val descriptorSignatureProvider: DescriptorSignatureProvider) { + val elementSignatureProvider: ElementSignatureProvider) { fun tryResolveContentLink(fromDescriptor: DeclarationDescriptor, href: String): ContentBlock? { @@ -34,7 +31,7 @@ class DeclarationLinkResolver if (externalHref != null) { return ContentExternalLink(externalHref) } - val signature = descriptorSignatureProvider.signature(symbol) + val signature = elementSignatureProvider.signature(symbol) val referencedAt = fromDescriptor.signatureWithSourceLocation() return ContentNodeLazyLink(href, { -> diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 6e44df74..5f1118e8 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -33,7 +33,9 @@ class DescriptorDocumentationParser val linkResolver: DeclarationLinkResolver, val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, - val sampleService: SampleProcessingService) + val sampleService: SampleProcessingService, + val signatureProvider: KotlinElementSignatureProvider + ) { fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false): Content = parseDocumentationAndDetails(descriptor, inline).first @@ -129,7 +131,7 @@ class DescriptorDocumentationParser fun parseJavadoc(descriptor: DeclarationDescriptor): Pair Unit> { val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi if (psi is PsiDocCommentOwner) { - val parseResult = JavadocParser(refGraph, logger).parseDocumentation(psi as PsiNamedElement) + val parseResult = JavadocParser(refGraph, logger, signatureProvider).parseDocumentation(psi as PsiNamedElement) return parseResult.content to { node -> parseResult.deprecatedContent?.let { val deprecationNode = DocumentationNode("", it, NodeKind.Modifier) diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index d7d30ebb..05bd2cc7 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.idea.util.toFuzzyType 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 @@ -29,7 +28,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors -import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement @@ -192,14 +190,16 @@ class DocumentationBuilder appendTextNode(modifier, NodeKind.Modifier) } - fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType) { + fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType, backref: Boolean) { val unwrappedType = superType.unwrap() if (unwrappedType is AbbreviatedType) { - appendSupertype(descriptor, unwrappedType.abbreviation) + appendSupertype(descriptor, unwrappedType.abbreviation, backref) } else { appendType(unwrappedType, NodeKind.Supertype) val superclass = unwrappedType.constructor.declarationDescriptor - link(superclass, descriptor, RefKind.Inheritor) + if (backref) { + link(superclass, descriptor, RefKind.Inheritor) + } link(descriptor, superclass, RefKind.Superclass) } } @@ -457,7 +457,7 @@ class DocumentationBuilder if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue logger.info(" package $packageName: ${declarations.count()} declarations") - val packageNode = findOrCreatePackageNode(packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) + val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode, declarations, allFqNames) } @@ -646,7 +646,7 @@ class DocumentationBuilder val node = nodeForDescriptor(this, kind, external) register(this, node) typeConstructor.supertypes.forEach { - node.appendSupertype(this, it) + node.appendSupertype(this, it, !external) } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) @@ -997,16 +997,11 @@ class KotlinJavaDocumentationBuilder val logger: DokkaLogger) : JavaDocumentationBuilder { override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map) { val classDescriptors = file.classes.map { - val javaDescriptorResolver = resolutionFacade.getFrontendService(JavaDescriptorResolver::class.java) - - javaDescriptorResolver.resolveClass(JavaClassImpl(it)) ?: run { - logger.warn("Cannot find descriptor for Java class ${it.qualifiedName}") - null - } + it.getJavaClassDescriptor(resolutionFacade) } if (classDescriptors.any { it != null && it.isDocumented(options) }) { - val packageNode = module.findOrCreatePackageNode(file.packageName, packageContent, documentationBuilder.refGraph) + val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph) for (descriptor in classDescriptors.filterNotNull()) { with(documentationBuilder) { diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt deleted file mode 100644 index a3be658e..00000000 --- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt +++ /dev/null @@ -1,22 +0,0 @@ -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/KotlinAsJavaElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt new file mode 100644 index 00000000..20ea179e --- /dev/null +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt @@ -0,0 +1,25 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.asJava.toLightElements +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.KtElement + +class KotlinAsJavaElementSignatureProvider : ElementSignatureProvider { + + private fun PsiElement.javaLikePsi() = when { + this is KtElement -> toLightElements().firstOrNull() + else -> this + } + + override fun signature(forPsi: PsiElement): String { + return getSignature(forPsi.javaLikePsi()) ?: + "not implemented for $forPsi" + } + + override fun signature(forDesc: DeclarationDescriptor): String { + val sourcePsi = forDesc.sourcePsi() + return getSignature(sourcePsi?.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 deleted file mode 100644 index 7ecd0389..00000000 --- a/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt +++ /dev/null @@ -1,9 +0,0 @@ -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/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt new file mode 100644 index 00000000..4f788634 --- /dev/null +++ b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt @@ -0,0 +1,31 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMember +import com.intellij.psi.PsiNameIdentifierOwner +import org.jetbrains.kotlin.asJava.elements.KtLightElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.resolve.BindingContext +import javax.inject.Inject + +class KotlinElementSignatureProvider @Inject constructor( + val resolutionFacade: DokkaResolutionFacade +) : ElementSignatureProvider { + override fun signature(forPsi: PsiElement): String { + + val desc = when (forPsi) { + is KtLightElement<*, *> -> return signature(forPsi.kotlinOrigin!!) + is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) + else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] + } + + if (desc == null && (forPsi as? PsiNameIdentifierOwner)?.name == "remove") { + (forPsi as? PsiMember)?.getJavaOrKotlinMemberDescriptor(resolutionFacade) + } + + return desc?.let { signature(it) } + ?: run { "no desc for $forPsi in ${(forPsi as? PsiMember)?.containingClass}" } + } + + 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 deleted file mode 100644 index 85584e3c..00000000 --- a/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt +++ /dev/null @@ -1,7 +0,0 @@ -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/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 84501d2b..4739d736 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -176,16 +176,17 @@ val DocumentationNode.path: List return parent.path + this } -fun DocumentationNode.findOrCreatePackageNode(packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { - val existingNode = members(NodeKind.Package).firstOrNull { it.name == packageName } +fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { + val existingNode = refGraph.lookup(packageName) if (existingNode != null) { return existingNode } val newNode = DocumentationNode(packageName, packageContent.getOrElse(packageName) { Content.Empty }, NodeKind.Package) - append(newNode, RefKind.Member) + refGraph.register(packageName, newNode) + module?.append(newNode, RefKind.Member) return newNode } diff --git a/core/src/main/kotlin/Model/ElementSignatureProvider.kt b/core/src/main/kotlin/Model/ElementSignatureProvider.kt new file mode 100644 index 00000000..e8fdde6e --- /dev/null +++ b/core/src/main/kotlin/Model/ElementSignatureProvider.kt @@ -0,0 +1,9 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +interface ElementSignatureProvider { + fun signature(forDesc: DeclarationDescriptor): String + fun signature(forPsi: PsiElement): String +} \ No newline at end of file diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 36704918..907d5ca7 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -2,14 +2,11 @@ package org.jetbrains.dokka.Utilities import com.google.inject.Binder import com.google.inject.Module -import com.google.inject.Provider import com.google.inject.TypeLiteral import com.google.inject.binder.AnnotatedBindingBuilder 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 import kotlin.reflect.KClass -- cgit From b00dabc4c53a71f745c29a135541b02f8dd7d266 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 4 May 2018 21:35:02 +0300 Subject: [backport] KT-24271: Support external link resolution in JavadocParser Original: ace3914 --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 8 ++-- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 10 ++++- core/src/main/kotlin/Java/JavadocParser.kt | 51 ++++++++++++++++------ .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 12 +++-- .../Kotlin/ExternalDocumentationLinkResolver.kt | 14 ++++-- .../Kotlin/KotlinElementSignatureProvider.kt | 30 ++++++------- core/src/main/kotlin/Utilities/DokkaModules.kt | 3 +- 7 files changed, 87 insertions(+), 41 deletions(-) (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index 6854b323..d31fe187 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -99,7 +99,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } - fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair { val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() @@ -164,15 +164,17 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { builtIns = builtIns ) - resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly val resolverForModule = resolverForProject.resolverForModule(module) + val libraryModuleDescriptor = resolverForProject.descriptorForModule(library) val moduleDescriptor = resolverForProject.descriptorForModule(module) builtIns.initialize(moduleDescriptor, true) + val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary) val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) val projectComponentManager = environment.project as MockComponentManager projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) - return created + return created to libraryResolutionFacade } fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 646096e5..8b30a6b4 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -45,10 +45,16 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser - @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger, signatureProvider: ElementSignatureProvider) { + @Inject constructor( + options: DocumentationOptions, + refGraph: NodeReferenceGraph, + logger: DokkaLogger, + signatureProvider: ElementSignatureProvider, + externalDocumentationLinkResolver: ExternalDocumentationLinkResolver + ) { this.options = options this.refGraph = refGraph - this.docParser = JavadocParser(refGraph, logger, signatureProvider) + this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver) } constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 5e23e357..e1b15cb2 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -26,7 +26,8 @@ interface JavaDocumentationParser { class JavadocParser( private val refGraph: NodeReferenceGraph, private val logger: DokkaLogger, - private val signatureProvider: ElementSignatureProvider + private val signatureProvider: ElementSignatureProvider, + private val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver ) : JavaDocumentationParser { private fun ContentSection.appendTypeElement(signature: String, selector: (DocumentationNode) -> DocumentationNode?) { @@ -197,25 +198,41 @@ class JavadocParser( private fun MutableContent.convertSeeTag(tag: PsiDocTag) { val linkElement = tag.linkElement() ?: return val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) - val linkSignature = resolveLink(tag.referenceElement()) + + val valueElement = tag.referenceElement() + val externalLink = resolveExternalLink(valueElement) val text = ContentText(linkElement.text) - if (linkSignature != null) { - val linkNode = - ContentNodeLazyLink((tag.valueElement ?: linkElement).text, { -> refGraph.lookupOrWarn(linkSignature, logger) }) - linkNode.append(text) - seeSection.append(linkNode) - } else { - seeSection.append(text) + + val linkSignature by lazy { resolveInternalLink(valueElement) } + val node = when { + externalLink != null -> { + val linkNode = ContentExternalLink(externalLink) + linkNode.append(text) + linkNode + } + linkSignature != null -> { + val linkNode = + ContentNodeLazyLink( + (tag.valueElement ?: linkElement).text, + { -> refGraph.lookupOrWarn(linkSignature, logger) } + ) + linkNode.append(text) + linkNode + } + else -> text } + seeSection.append(node) } private fun convertInlineDocTag(tag: PsiInlineDocTag, element: PsiNamedElement) = when (tag.name) { "link", "linkplain" -> { val valueElement = tag.referenceElement() - val linkSignature = resolveLink(valueElement) - if (linkSignature != null) { + val externalLink = resolveExternalLink(valueElement) + val linkSignature by lazy { resolveInternalLink(valueElement) } + if (externalLink != null || linkSignature != null) { val labelText = tag.dataElements.firstOrNull { it is PsiDocToken }?.text ?: valueElement!!.text - val link = "${labelText.htmlEscape()}" + val linkTarget = if (externalLink != null) "href=\"$externalLink\"" else "docref=\"$linkSignature\"" + val link = "${labelText.htmlEscape()}" if (tag.name == "link") "$link" else link } else if (valueElement != null) { valueElement.text @@ -256,7 +273,15 @@ class JavadocParser( private fun PsiDocTag.linkElement(): PsiElement? = valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } - private fun resolveLink(valueElement: PsiElement?): String? { + private fun resolveExternalLink(valueElement: PsiElement?): String? { + val target = valueElement?.reference?.resolve() + if (target != null) { + return externalDocumentationLinkResolver.buildExternalDocumentationLink(target) + } + return null + } + + private fun resolveInternalLink(valueElement: PsiElement?): String? { val target = valueElement?.reference?.resolve() if (target != null) { return signatureProvider.signature(target) diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 5f1118e8..7817da18 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -34,8 +34,9 @@ class DescriptorDocumentationParser val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, val sampleService: SampleProcessingService, - val signatureProvider: KotlinElementSignatureProvider - ) + val signatureProvider: KotlinElementSignatureProvider, + val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver +) { fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false): Content = parseDocumentationAndDetails(descriptor, inline).first @@ -131,7 +132,12 @@ class DescriptorDocumentationParser fun parseJavadoc(descriptor: DeclarationDescriptor): Pair Unit> { val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi if (psi is PsiDocCommentOwner) { - val parseResult = JavadocParser(refGraph, logger, signatureProvider).parseDocumentation(psi as PsiNamedElement) + val parseResult = JavadocParser( + refGraph, + logger, + signatureProvider, + externalDocumentationLinkResolver + ).parseDocumentation(psi as PsiNamedElement) return parseResult.content to { node -> parseResult.deprecatedContent?.let { val deprecationNode = DocumentationNode("", it, NodeKind.Modifier) diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 7be37177..c766b869 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.Singleton +import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.util.io.* import org.jetbrains.dokka.Formats.FileGeneratorBasedFormatDescriptor @@ -10,10 +11,7 @@ import org.jetbrains.dokka.Utilities.ServiceLocator import org.jetbrains.dokka.Utilities.lookup import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor +import org.jetbrains.kotlin.load.java.descriptors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -25,6 +23,7 @@ import java.net.URL import java.net.URLConnection import java.nio.file.Path import java.security.MessageDigest +import javax.inject.Named import kotlin.reflect.full.findAnnotation fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) } @@ -32,6 +31,7 @@ fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format( @Singleton class ExternalDocumentationLinkResolver @Inject constructor( val options: DocumentationOptions, + @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, val logger: DokkaLogger ) { @@ -166,6 +166,12 @@ class ExternalDocumentationLinkResolver @Inject constructor( } } + fun buildExternalDocumentationLink(element: PsiElement): String? { + return element.extractDescriptor(libraryResolutionFacade)?.let { + buildExternalDocumentationLink(it) + } + } + fun buildExternalDocumentationLink(symbol: DeclarationDescriptor): String? { val packageFqName: FqName = when (symbol) { diff --git a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt index 0a377dc1..bcac0182 100644 --- a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt +++ b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import com.intellij.psi.PsiElement import com.intellij.psi.PsiMember -import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.PsiPackage import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -14,21 +13,22 @@ class KotlinElementSignatureProvider @Inject constructor( val resolutionFacade: DokkaResolutionFacade ) : ElementSignatureProvider { override fun signature(forPsi: PsiElement): String { - - val desc = when (forPsi) { - is KtLightElement<*, *> -> return signature(forPsi.kotlinOrigin!!) - is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName)) - is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) - else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] - } - - if (desc == null && (forPsi as? PsiNameIdentifierOwner)?.name == "remove") { - (forPsi as? PsiMember)?.getJavaOrKotlinMemberDescriptor(resolutionFacade) - } - - return desc?.let { signature(it) } + return forPsi.extractDescriptor(resolutionFacade) + ?.let { signature(it) } ?: run { "no desc for $forPsi in ${(forPsi as? PsiMember)?.containingClass}" } } override fun signature(forDesc: DeclarationDescriptor): String = forDesc.signature() -} \ No newline at end of file +} + + +fun PsiElement.extractDescriptor(resolutionFacade: DokkaResolutionFacade): DeclarationDescriptor? { + val forPsi = this + + return when (forPsi) { + is KtLightElement<*, *> -> return (forPsi.kotlinOrigin!!).extractDescriptor(resolutionFacade) + is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName)) + is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) + else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] + } +} diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 907d5ca7..732cbc48 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -24,8 +24,9 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, val coreEnvironment = environment.createCoreEnvironment() binder.bind().toInstance(coreEnvironment) - val dokkaResolutionFacade = environment.createResolutionFacade(coreEnvironment) + val (dokkaResolutionFacade, libraryResolutionFacade) = environment.createResolutionFacade(coreEnvironment) binder.bind().toInstance(dokkaResolutionFacade) + binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) binder.bind().toInstance(options) -- cgit From 052a218dcf8bc565d5e78dc900a9647f0da5350a Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Wed, 1 Aug 2018 19:48:45 +0300 Subject: Refactoring, replace DocumentationOption with PassConfiguration --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 32 +----- core/src/main/kotlin/Generation/DokkaGenerator.kt | 58 +++++------ core/src/main/kotlin/Generation/FileGenerator.kt | 5 +- .../main/kotlin/Generation/configurationImpl.kt | 70 ++++++++----- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 25 +++-- .../main/kotlin/Kotlin/DeclarationLinkResolver.kt | 4 +- .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 2 +- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 108 ++++++--------------- .../Kotlin/ExternalDocumentationLinkResolver.kt | 13 ++- .../Kotlin/KotlinAsJavaDocumentationBuilder.kt | 2 +- .../Samples/DefaultSampleProcessingService.kt | 2 +- .../KotlinWebsiteSampleProcessingService.kt | 4 +- core/src/main/kotlin/Utilities/DokkaModules.kt | 18 ++-- core/src/main/kotlin/javadoc/dokka-adapters.kt | 9 +- core/src/test/kotlin/TestAPI.kt | 44 +++++---- .../test/kotlin/format/KotlinWebSiteFormatTest.kt | 19 ++-- .../kotlin/format/KotlinWebSiteHtmlFormatTest.kt | 22 +++-- core/src/test/kotlin/format/MarkdownFormatTest.kt | 36 ++++--- .../kotlin/org/jetbrains/dokka/configuration.kt | 71 ++++++-------- runners/ant/src/main/kotlin/ant/dokka.kt | 49 +++++----- runners/cli/src/main/kotlin/cli/main.kt | 36 ++++--- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 47 ++++----- 22 files changed, 323 insertions(+), 353 deletions(-) (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index e18ab6cf..ccafcd12 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import org.jetbrains.dokka.DokkaConfiguration.PackageOptions import ru.yole.jkid.deserialization.deserialize -import java.io.File import java.util.function.BiConsumer @@ -44,36 +43,7 @@ class DokkaBootstrapImpl : DokkaBootstrap { = configure(DokkaProxyLogger(logger), deserialize(serializedConfigurationJSON)) fun configure(logger: DokkaLogger, configuration: DokkaConfiguration) = with(configuration) { - generator = DokkaGenerator( - logger, - classpath, - sourceRoots, - samples, - includes, - moduleName, - DocumentationOptions( - outputDir = outputDir, - outputFormat = format, - includeNonPublic = includeNonPublic, - includeRootPackage = includeRootPackage, - reportUndocumented = reportUndocumented, - skipEmptyPackages = skipEmptyPackages, - skipDeprecated = skipDeprecated, - jdkVersion = jdkVersion, - generateIndexPages = generateIndexPages, - sourceLinks = sourceLinks, - impliedPlatforms = impliedPlatforms, - perPackageOptions = perPackageOptions, - externalDocumentationLinks = externalDocumentationLinks, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - languageVersion = languageVersion, - apiVersion = apiVersion, - cacheRoot = cacheRoot, - suppressedFiles = suppressedFiles.map { File(it) }.toSet(), - collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries - ) - ) + generator = DokkaGenerator(configuration, logger) } override fun generate() = generator.generate() diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 0c4b3b7e..2e46d908 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -2,13 +2,11 @@ package org.jetbrains.dokka import com.google.inject.Guice import com.google.inject.Injector -import com.intellij.openapi.application.PathManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager -import org.jetbrains.dokka.DokkaConfiguration.SourceRoot import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation @@ -18,7 +16,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.KotlinSourceRoot import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode @@ -26,56 +23,49 @@ import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis -class DokkaGenerator(val logger: DokkaLogger, - val classpath: List, - val sources: List, - val samples: List, - val includes: List, - val moduleName: String, - val options: DocumentationOptions) { +class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, + val logger: DokkaLogger) { private val documentationModules: MutableList = mutableListOf() - fun generate() { - val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } - for ((platformsInfo, roots) in sourcesGroupedByPlatform) { - val (platform, analysisPlatform) = platformsInfo - val documentationModule = DocumentationModule(moduleName) - appendSourceModule(platform, analysisPlatform, roots, documentationModule) + fun generate() = with(dokkaConfiguration) { + + + for (pass in passesConfigurations) { + val documentationModule = DocumentationModule(pass.moduleName) + appendSourceModule(pass, documentationModule) documentationModules.add(documentationModule) } val totalDocumentationModule = DocumentationMerger(documentationModules).merge() - totalDocumentationModule.prepareForGeneration(options) + totalDocumentationModule.prepareForGeneration(dokkaConfiguration) val timeBuild = measureTimeMillis { logger.info("Generating pages... ") - val outputInjector = Guice.createInjector(DokkaOutputModule(options, logger)) + val outputInjector = Guice.createInjector(DokkaOutputModule(dokkaConfiguration, logger)) outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } private fun appendSourceModule( - defaultPlatform: String?, - analysisPlatform: Platform, - sourceRoots: List, + passConfiguration: DokkaConfiguration.PassConfiguration, documentationModule: DocumentationModule - ) { + ) = with(passConfiguration) { - val sourcePaths = sourceRoots.map { it.path } - val environment = createAnalysisEnvironment(sourcePaths, analysisPlatform) + val sourcePaths = passConfiguration.sourceRoots.map { it.path } + val environment = createAnalysisEnvironment(sourcePaths, passConfiguration) logger.info("Module: $moduleName") - logger.info("Output: ${File(options.outputDir)}") + logger.info("Output: ${File(dokkaConfiguration.outputDir)}") logger.info("Sources: ${sourcePaths.joinToString()}") logger.info("Classpath: ${environment.classpath.joinToString()}") logger.info("Analysing sources and libraries... ") val startAnalyse = System.currentTimeMillis() - val defaultPlatformAsList = defaultPlatform?.let { listOf(it) }.orEmpty() + val defaultPlatformAsList = listOf(passConfiguration.analysisPlatform.key) val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List { val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath @@ -86,9 +76,9 @@ class DokkaGenerator(val logger: DokkaLogger, } val injector = Guice.createInjector( - DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentationModule.nodeRefGraph, logger)) + DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) - buildDocumentationModule(injector, documentationModule, { isNotSample(it) }, includes) + buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> node.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), @@ -102,28 +92,28 @@ class DokkaGenerator(val logger: DokkaLogger, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List, analysisPlatform: Platform): AnalysisEnvironment { - val environment = AnalysisEnvironment(DokkaMessageCollector(logger), analysisPlatform) + fun createAnalysisEnvironment(sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration): AnalysisEnvironment { + val environment = AnalysisEnvironment(DokkaMessageCollector(logger), passConfiguration.analysisPlatform) environment.apply { if (analysisPlatform == Platform.jvm) { addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) } // addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) - for (element in this@DokkaGenerator.classpath) { + for (element in passConfiguration.classpath) { addClasspath(File(element)) } addSources(sourcePaths) - addSources(this@DokkaGenerator.samples) + addSources(passConfiguration.samples) - loadLanguageVersionSettings(options.languageVersion, options.apiVersion) + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) } return environment } - fun isNotSample(file: PsiFile): Boolean { + fun isNotSample(file: PsiFile, samples: List): Boolean { val sourceFile = File(file.virtualFile!!.path) return samples.none { sample -> val canonicalSample = File(sample).canonicalPath diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index b7c6cf63..eb6800b3 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named -import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -12,7 +11,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F @set:Inject(optional = true) var outlineService: OutlineFormatService? = null @set:Inject(optional = true) lateinit var formatService: FormatService - @set:Inject(optional = true) lateinit var options: DocumentationOptions + @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null override fun location(node: DocumentationNode): FileLocation { @@ -74,7 +73,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F val moduleRoot = location(module).file.parentFile val packageListFile = File(moduleRoot, "package-list") - packageListFile.writeText("\$dokka.format:${options.outputFormat}\n" + + packageListFile.writeText("\$dokka.format:${dokkaConfiguration.format}\n" + packageListService!!.formatPackageList(module as DocumentationModule)) } diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 8829682a..3e39b4ed 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -45,29 +45,47 @@ data class PackageOptionsImpl(override val prefix: String, override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions data class DokkaConfigurationImpl( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - 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, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val noJdkLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String?, - override val collectInheritedExtensionsFromLibraries: Boolean -) : DokkaConfiguration \ No newline at end of file + override val outputDir: String = "", + override val format: String = "html", + override val generateIndexPages: Boolean = false, + override val cacheRoot: String? = null, + override val impliedPlatforms: List = listOf(), + override val passesConfigurations: List = listOf() +) : DokkaConfiguration + +class PassConfigurationImpl ( + override val classpath: List = listOf(), + override val moduleName: String = "", + override val sourceRoots: List = listOf(), + override val samples: List = listOf(), + override val includes: List = listOf(), + override val includeNonPublic: Boolean = false, + override val includeRootPackage: Boolean = false, + override val reportUndocumented: Boolean = false, + override val skipEmptyPackages: Boolean = false, + override val skipDeprecated: Boolean = false, + override val jdkVersion: Int = 6, + override val sourceLinks: List = listOf(), + override val perPackageOptions: List = listOf(), + externalDocumentationLinks: List = listOf(), + override val languageVersion: String? = null, + override val apiVersion: String? = null, + override val noStdlibLink: Boolean = false, + override val noJdkLink: Boolean = false, + override val suppressedFiles: List = listOf(), + override val collectInheritedExtensionsFromLibraries: Boolean = false, + override val analysisPlatform: Platform = Platform.DEFAULT, + override val targets: List = listOf() +): DokkaConfiguration.PassConfiguration { + private val defaultLinks = run { + val links = mutableListOf() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() + links + } + override val externalDocumentationLinks = defaultLinks + externalDocumentationLinks +} + diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 332afffb..1fe4d180 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -13,7 +13,6 @@ 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 PsiPackage -> element.qualifiedName @@ -44,24 +43,24 @@ interface JavaDocumentationBuilder { } class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { - private val options: DocumentationOptions + private val passConfiguration: DokkaConfiguration.PassConfiguration private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser @Inject constructor( - options: DocumentationOptions, - refGraph: NodeReferenceGraph, - logger: DokkaLogger, - signatureProvider: ElementSignatureProvider, - externalDocumentationLinkResolver: ExternalDocumentationLinkResolver + passConfiguration: DokkaConfiguration.PassConfiguration, + refGraph: NodeReferenceGraph, + logger: DokkaLogger, + signatureProvider: ElementSignatureProvider, + externalDocumentationLinkResolver: ExternalDocumentationLinkResolver ) { - this.options = options + this.passConfiguration = passConfiguration this.refGraph = refGraph this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver) } - constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { - this.options = options + constructor(passConfiguration: DokkaConfiguration.PassConfiguration, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { + this.passConfiguration = passConfiguration this.refGraph = refGraph this.docParser = docParser } @@ -141,7 +140,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { } } - private fun skipFile(javaFile: PsiJavaFile): Boolean = options.effectivePackageOptions(javaFile.packageName).suppress + private fun skipFile(javaFile: PsiJavaFile): Boolean = passConfiguration.effectivePackageOptions(javaFile.packageName).suppress private fun skipElement(element: Any) = skipElementByVisibility(element) || @@ -151,13 +150,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private fun skipElementByVisibility(element: Any): Boolean = element is PsiModifierListOwner && element !is PsiParameter && - !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && + !(passConfiguration.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && (element.hasModifierProperty(PsiModifier.PRIVATE) || 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 + element is PsiElement && element.containingFile.virtualFile.path in passConfiguration.suppressedFiles private fun PsiElement.isInternal(): Boolean { val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index d73bef4a..c3a84e57 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -10,7 +10,7 @@ class DeclarationLinkResolver @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, val logger: DokkaLogger, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver, val elementSignatureProvider: ElementSignatureProvider) { @@ -63,7 +63,7 @@ class DeclarationLinkResolver if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { return symbol.overriddenDescriptors.firstOrNull() } - if (symbol is TypeAliasDescriptor && !symbol.isDocumented(options)) { + if (symbol is TypeAliasDescriptor && !symbol.isDocumented(passConfiguration)) { return symbol.classDescriptor } return symbol diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 7817da18..d0650d45 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement class DescriptorDocumentationParser - @Inject constructor(val options: DocumentationOptions, + @Inject constructor(val options: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger, val linkResolver: DeclarationLinkResolver, val resolutionFacade: DokkaResolutionFacade, diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e3675f9d..fb0b898a 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -4,7 +4,7 @@ import com.google.inject.Inject import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiField import com.intellij.psi.PsiJavaFile -import org.jetbrains.dokka.DokkaConfiguration.* +import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* @@ -35,62 +35,8 @@ import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.util.supertypesWithAny -import java.io.File -import java.nio.file.Path -import java.nio.file.Paths import com.google.inject.name.Named as GuiceNamed -class DocumentationOptions(val outputDir: String, - val outputFormat: String, - includeNonPublic: Boolean = false, - val includeRootPackage: Boolean = false, - reportUndocumented: Boolean = true, - val skipEmptyPackages: Boolean = true, - skipDeprecated: Boolean = false, - jdkVersion: Int = 6, - val generateIndexPages: Boolean = true, - val sourceLinks: List = emptyList(), - val impliedPlatforms: List = emptyList(), - // Sorted by pattern length - perPackageOptions: List = emptyList(), - externalDocumentationLinks: List = emptyList(), - noStdlibLink: Boolean, - noJdkLink: Boolean = false, - val languageVersion: String?, - val apiVersion: String?, - cacheRoot: String? = null, - val suppressedFiles: Set = emptySet(), - val collectInheritedExtensionsFromLibraries: Boolean = false) { - init { - if (perPackageOptions.any { it.prefix == "" }) - throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead") - } - - val perPackageOptions = perPackageOptions.sortedByDescending { it.prefix.length } - val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated) - - fun effectivePackageOptions(pack: String): PackageOptions = perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions - fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString()) - - val defaultLinks = run { - val links = mutableListOf() - if (!noJdkLink) - links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() - - if (!noStdlibLink) - links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() - links - } - - val externalDocumentationLinks = defaultLinks + externalDocumentationLinks - - val cacheRoot: Path? = when { - cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") - cacheRoot != null -> Paths.get(cacheRoot) - else -> null - } -} - private fun isExtensionForExternalClass(extensionFunctionDescriptor: DeclarationDescriptor, extensionReceiverDescriptor: DeclarationDescriptor, allFqNames: Collection): Boolean { @@ -120,7 +66,7 @@ val ignoredSupertypes = setOf( class DocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val descriptorDocumentationParser: DescriptorDocumentationParser, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val refGraph: NodeReferenceGraph, val platformNodeRegistry: PlatformNodeRegistry, val logger: DokkaLogger, @@ -352,7 +298,7 @@ class DocumentationBuilder fun DocumentationNode.isSinceKotlin() = name == "SinceKotlin" && kind == NodeKind.Annotation fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) { - appendSourceLink(sourceElement.getPsi(), options.sourceLinks) + appendSourceLink(sourceElement.getPsi(), passConfiguration.sourceLinks) } fun DocumentationNode.appendSignature(descriptor: DeclarationDescriptor) { @@ -360,7 +306,7 @@ class DocumentationBuilder } fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? { - if (!descriptor.isGenerated() && descriptor.isDocumented(options)) { + if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) { val node = descriptor.build() append(node, kind) return node @@ -387,7 +333,7 @@ class DocumentationBuilder fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) { - if (descriptor.isGenerated() || !descriptor.isDocumented(options)) return + if (descriptor.isGenerated() || !descriptor.isDocumented(passConfiguration)) return val existingNode = refGraph.lookup(descriptor.signature()) if (existingNode != null) { @@ -459,10 +405,10 @@ class DocumentationBuilder val allFqNames = fragments.map { it.fqName }.distinct() for (packageName in allFqNames) { - if (packageName.isRoot && !options.includeRootPackage) continue + if (packageName.isRoot && !passConfiguration.includeRootPackage) continue val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getContributedDescriptors() } - if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue + if (passConfiguration.skipEmptyPackages && declarations.none { it.isDocumented(passConfiguration) }) continue logger.info(" package $packageName: ${declarations.count()} declarations") val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode, @@ -489,7 +435,7 @@ class DocumentationBuilder }.flatten() val allDescriptors = - if (options.collectInheritedExtensionsFromLibraries) { + if (passConfiguration.collectInheritedExtensionsFromLibraries) { allPackageViewDescriptors.map { it.memberScope } } else { fragments.asSequence().map { it.getMemberScope() } @@ -694,7 +640,7 @@ class DocumentationBuilder .mapTo(result) { ClassMember(it, extraModifier = "static") } val companionObjectDescriptor = companionObjectDescriptor - if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(options)) { + if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(passConfiguration)) { val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors() val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() } descriptorsToDocument.mapTo(result) { @@ -967,12 +913,12 @@ class DocumentationBuilder } -fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean { - return (options.effectivePackageOptions(fqNameSafe).includeNonPublic +fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean { + return (passConfiguration.effectivePackageOptions(fqNameSafe).includeNonPublic || this !is MemberDescriptor || this.visibility.isPublicAPI) - && !isDocumentationSuppressed(options) - && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) + && !isDocumentationSuppressed(passConfiguration) + && (!passConfiguration.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) } private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION @@ -986,7 +932,7 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { val externalClassNodes = hashMapOf() declarations.forEach { descriptor -> with(documentationBuilder) { - if (descriptor.isDocumented(options)) { + if (descriptor.isDocumented(passConfiguration)) { val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames) parent.appendOrUpdateMember(descriptor) } @@ -998,14 +944,14 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { class KotlinJavaDocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val documentationBuilder: DocumentationBuilder, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger) : JavaDocumentationBuilder { override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map) { val classDescriptors = file.classes.map { it.getJavaClassDescriptor(resolutionFacade) } - if (classDescriptors.any { it != null && it.isDocumented(options) }) { + if (classDescriptors.any { it != null && it.isDocumented(passConfiguration) }) { val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph) for (descriptor in classDescriptors.filterNotNull()) { @@ -1035,13 +981,13 @@ fun AnnotationDescriptor.mustBeDocumented(): Boolean { return annotationClass.isDocumentedAnnotation() } -fun DeclarationDescriptor.isDocumentationSuppressed(options: DocumentationOptions): Boolean { +fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean { - if (options.effectivePackageOptions(fqNameSafe).suppress) return true + if (passConfiguration.effectivePackageOptions(fqNameSafe).suppress) return true val path = this.findPsi()?.containingFile?.virtualFile?.path if (path != null) { - if (File(path).absoluteFile in options.suppressedFiles) return true + if (path in passConfiguration.suppressedFiles) return true } val doc = findKDoc() @@ -1079,7 +1025,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name @@ -1140,8 +1086,8 @@ fun DeclarationDescriptor.sourceLocation(): String? { return null } -fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) { - if (options.generateIndexPages) { +fun DocumentationModule.prepareForGeneration(configuration: DokkaConfiguration) { + if (configuration.generateIndexPages) { generateAllTypesNode() } nodeRefGraph.resolveReferences() @@ -1167,4 +1113,12 @@ fun ClassDescriptor.supertypesWithAnyPrecise(): Collection { return emptyList() } return typeConstructor.supertypesWithAny() -} \ No newline at end of file +} + +fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions { + val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated) + return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions +} + +fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString()) + diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index a8129793..2fc207b9 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -22,6 +22,7 @@ import java.net.HttpURLConnection import java.net.URL import java.net.URLConnection import java.nio.file.Path +import java.nio.file.Paths import java.security.MessageDigest import javax.inject.Named import kotlin.reflect.full.findAnnotation @@ -30,7 +31,8 @@ fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format( @Singleton class ExternalDocumentationLinkResolver @Inject constructor( - val options: DocumentationOptions, + val configuration: DokkaConfiguration, + val passConfiguration: DokkaConfiguration.PassConfiguration, @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, val logger: DokkaLogger ) { @@ -42,7 +44,12 @@ class ExternalDocumentationLinkResolver @Inject constructor( override fun toString(): String = rootUrl.toString() } - val cacheDir: Path? = options.cacheRoot?.resolve("packageListCache")?.apply { createDirectories() } + + val cacheDir: Path? = when { + configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") + configuration.cacheRoot != null -> Paths.get(configuration.cacheRoot) + else -> null + }?.resolve("packageListCache")?.apply { createDirectories() } val cachedProtocols = setOf("http", "https", "ftp") @@ -157,7 +164,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( } init { - options.externalDocumentationLinks.forEach { + passConfiguration.externalDocumentationLinks.forEach { try { loadPackageList(it) } catch (e: Exception) { diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt index c7ed8292..be6dd2e1 100644 --- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt @@ -28,7 +28,7 @@ class KotlinAsJavaDocumentationBuilder return } - val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.options, + val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.passConfiguration, documentationBuilder.refGraph, kotlinAsJavaDocumentationParser) diff --git a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt index 116a5c02..f3f45c3f 100644 --- a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.resolve.scopes.ResolutionScope open class DefaultSampleProcessingService -@Inject constructor(val options: DocumentationOptions, +@Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger, val resolutionFacade: DokkaResolutionFacade) : SampleProcessingService { diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index b0988c35..b5801457 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -12,10 +12,10 @@ import org.jetbrains.kotlin.psi.psiUtil.prevLeaf import org.jetbrains.kotlin.resolve.ImportPath open class KotlinWebsiteSampleProcessingService -@Inject constructor(options: DocumentationOptions, +@Inject constructor(dokkaConfiguration: DokkaConfiguration, logger: DokkaLogger, resolutionFacade: DokkaResolutionFacade) - : DefaultSampleProcessingService(options, logger, resolutionFacade) { + : DefaultSampleProcessingService(dokkaConfiguration, logger, resolutionFacade) { private class SampleBuilder : KtTreeVisitorVoid() { val builder = StringBuilder() diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 732cbc48..251d5c23 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -14,9 +14,10 @@ import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" class DokkaAnalysisModule(val environment: AnalysisEnvironment, - val options: DocumentationOptions, + val configuration: DokkaConfiguration, val defaultPlatformsProvider: DefaultPlatformsProvider, val nodeReferenceGraph: NodeReferenceGraph, + val passConfiguration: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { binder.bind().toInstance(logger) @@ -28,29 +29,30 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(dokkaResolutionFacade) binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) - binder.bind().toInstance(options) + binder.bind().toInstance(configuration) + binder.bind().toInstance(passConfiguration) binder.bind().toInstance(defaultPlatformsProvider) binder.bind().toInstance(nodeReferenceGraph) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) + val descriptor = ServiceLocator.lookup("format", configuration.format) descriptor.configureAnalysis(binder) } } object StringListType : TypeLiteral<@JvmSuppressWildcards List>() -class DokkaOutputModule(val options: DocumentationOptions, +class DokkaOutputModule(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) + binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) - binder.bind().toInstance(options) + binder.bind().toInstance(configuration) binder.bind().toInstance(logger) - binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(options.impliedPlatforms) + binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) + val descriptor = ServiceLocator.lookup("format", configuration.format) descriptor.configureOutput(binder) } diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt index 483fb3cd..1329876a 100644 --- a/core/src/main/kotlin/javadoc/dokka-adapters.kt +++ b/core/src/main/kotlin/javadoc/dokka-adapters.kt @@ -4,16 +4,19 @@ import com.google.inject.Binder import com.google.inject.Inject import com.sun.tools.doclets.formats.html.HtmlDoclet import org.jetbrains.dokka.* -import org.jetbrains.dokka.Formats.* +import org.jetbrains.dokka.Formats.DefaultAnalysisComponent +import org.jetbrains.dokka.Formats.DefaultAnalysisComponentServices +import org.jetbrains.dokka.Formats.FormatDescriptor +import org.jetbrains.dokka.Formats.KotlinAsJava import org.jetbrains.dokka.Utilities.bind import org.jetbrains.dokka.Utilities.toType -class JavadocGenerator @Inject constructor(val options: DocumentationOptions, val logger: DokkaLogger) : Generator { +class JavadocGenerator @Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Generator { override fun buildPages(nodes: Iterable) { val module = nodes.single() as DocumentationModule - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), options.outputDir)) + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), configuration.outputDir)) } override fun buildOutlines(nodes: Iterable) { diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 4a755130..b65efbe9 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -35,31 +35,35 @@ fun verifyModel(modelConfig: ModelConfig, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") - val options = DocumentationOptions( - "", - modelConfig.format, - includeNonPublic = modelConfig.includeNonPublic, - skipEmptyPackages = false, - includeRootPackage = true, - sourceLinks = listOf(), - perPackageOptions = modelConfig.perPackageOptions, - generateIndexPages = false, - noStdlibLink = modelConfig.noStdlibLink, - noJdkLink = false, - cacheRoot = "default", - languageVersion = null, - apiVersion = null, - collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + val passConfiguration = PassConfigurationImpl ( + includeNonPublic = modelConfig.includeNonPublic, + skipEmptyPackages = false, + includeRootPackage = true, + sourceLinks = listOf(), + perPackageOptions = modelConfig.perPackageOptions, + noStdlibLink = modelConfig.noStdlibLink, + noJdkLink = false, + languageVersion = null, + apiVersion = null, + collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = modelConfig.format, + generateIndexPages = false, + cacheRoot = "default", + passesConfigurations = listOf(passConfiguration) ) - appendDocumentation(documentation, options, modelConfig) - documentation.prepareForGeneration(options) + appendDocumentation(documentation, configuration, passConfiguration, modelConfig) + documentation.prepareForGeneration(configuration) verifier(documentation) } fun appendDocumentation(documentation: DocumentationModule, - options: DocumentationOptions, + dokkaConfiguration: DokkaConfiguration, + passConfiguration: DokkaConfiguration.PassConfiguration, modelConfig: ModelConfig ) { val messageCollector = object : MessageCollector { @@ -108,13 +112,13 @@ fun appendDocumentation(documentation: DocumentationModule, } addRoots(modelConfig.roots.toList()) - loadLanguageVersionSettings(options.languageVersion, options.apiVersion) + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) } val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms } val injector = Guice.createInjector( - DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentation.nodeRefGraph, DokkaConsoleLogger)) + DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentation.nodeRefGraph, passConfiguration, DokkaConsoleLogger)) buildDocumentationModule(injector, documentation) Disposer.dispose(environment) } diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt index 643b5b2d..4f292e37 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt @@ -48,17 +48,20 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, - noStdlibLink = true, + val passConfiguration = PassConfigurationImpl(noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf(passConfiguration) + ) + appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/jvm.kt")), defaultPlatforms = listOf("JVM") ) @@ -67,13 +70,13 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/jre7.kt")), defaultPlatforms = listOf("JVM", "JRE7") ) ) appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/js.kt")), defaultPlatforms = listOf("JS") ) diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index 3ae0930e..1901154f 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -64,29 +64,37 @@ abstract class BaseKotlinWebSiteHtmlFormatTest(val analysisPlatform: Platform): private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "kotlin-website-html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "kotlin-website-html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + + ) + appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jvm.kt")), defaultPlatforms = listOf("JVM") ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jre7.kt")), defaultPlatforms = listOf("JVM", "JRE7") ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/js.kt")), defaultPlatforms = listOf("JS") ) diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 4de70751..29d2d20f 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -1,7 +1,6 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* -import org.junit.Before import org.junit.Test abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() { @@ -249,16 +248,23 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener @Test fun packagePlatformsWithExtExtensions() { val path = "multiplatform/packagePlatformsWithExtExtensions" val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) - appendDocumentation(module, options, ModelConfig( + + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + ) + + appendDocumentation(module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")), defaultPlatforms = listOf("JVM"), withKotlinRuntime = true, @@ -373,24 +379,30 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + + ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")), defaultPlatforms = listOf("JVM"), analysisPlatform = Platform.jvm ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/js.kt")), defaultPlatforms = listOf("JS"), analysisPlatform = Platform.js diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 287b628a..e0fa27d1 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -39,31 +39,37 @@ enum class Platform(val key: String) { } interface DokkaConfiguration { - val moduleName: String - val classpath: List - val sourceRoots: List - val samples: List - val includes: List val outputDir: String val format: String - val includeNonPublic: Boolean - val includeRootPackage: Boolean - val reportUndocumented: Boolean - val skipEmptyPackages: Boolean - val skipDeprecated: Boolean - val jdkVersion: Int val generateIndexPages: Boolean - val sourceLinks: List - val impliedPlatforms: List - val perPackageOptions: List - val externalDocumentationLinks: List - val languageVersion: String? - val apiVersion: String? - val noStdlibLink: Boolean - val noJdkLink: Boolean val cacheRoot: String? - val suppressedFiles: List - val collectInheritedExtensionsFromLibraries: Boolean + val passesConfigurations: List + val impliedPlatforms: List + + interface PassConfiguration { + val moduleName: String + val classpath: List + val sourceRoots: List + val samples: List + val includes: List + val includeNonPublic: Boolean + val includeRootPackage: Boolean + val reportUndocumented: Boolean + val skipEmptyPackages: Boolean + val skipDeprecated: Boolean + val jdkVersion: Int + val sourceLinks: List + val perPackageOptions: List + val externalDocumentationLinks: List + val languageVersion: String? + val apiVersion: String? + val noStdlibLink: Boolean + val noJdkLink: Boolean + val suppressedFiles: List + val collectInheritedExtensionsFromLibraries: Boolean + val analysisPlatform: Platform + val targets: List + } interface SourceRoot { val path: String @@ -106,31 +112,12 @@ interface DokkaConfiguration { } data class SerializeOnlyDokkaConfiguration( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, 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, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val noJdkLink: Boolean, override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String?, - override val collectInheritedExtensionsFromLibraries: Boolean + override val impliedPlatforms: List, + override val passesConfigurations: List ) : DokkaConfiguration diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 0b1ccc13..4f629198 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -116,29 +116,34 @@ class DokkaAntTask: Task() { SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix) } - val generator = DokkaGenerator( - AntLogger(this), - compileClasspath.list().toList(), - sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }, - samplesPath.list().toList(), - includesPath.list().toList(), - moduleName!!, - DocumentationOptions( - outputDir!!, - outputFormat, - skipDeprecated = skipDeprecated, - sourceLinks = sourceLinks, - jdkVersion = jdkVersion, - impliedPlatforms = impliedPlatforms.split(','), - perPackageOptions = antPackageOptions, - externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - cacheRoot = cacheRoot, - languageVersion = languageVersion, - apiVersion = apiVersion - ) + val passConfiguration = PassConfigurationImpl( + classpath = compileClasspath.list().toList(), + sourceRoots = sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }, + samples = samplesPath.list().toList(), + includes = includesPath.list().toList(), + moduleName = moduleName!!, + skipDeprecated = skipDeprecated, + sourceLinks = sourceLinks, + jdkVersion = jdkVersion, + perPackageOptions = antPackageOptions, + externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion ) + + val configuration = DokkaConfigurationImpl( + outputDir = outputDir!!, + format = outputFormat, + impliedPlatforms = impliedPlatforms.split(','), + cacheRoot = cacheRoot, + passesConfigurations = listOf( + passConfiguration + ) + ) + + val generator = DokkaGenerator(configuration, AntLogger(this)) generator.generate() } } \ No newline at end of file diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index f871f406..330de5e1 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,+suppress;...\" ") + @set:Argument(value = "packageOptions", description = "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ") var packageOptions: String = "" @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...") @@ -111,31 +111,37 @@ object MainKt { val classPath = arguments.classpath.split(File.pathSeparatorChar).toList() - val documentationOptions = DocumentationOptions( - arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, - arguments.outputFormat, + val passConfig = PassConfigurationImpl( skipDeprecated = arguments.nodeprecated, sourceLinks = sourceLinks, - impliedPlatforms = arguments.impliedPlatforms.split(','), perPackageOptions = parsePerPackageOptions(arguments.packageOptions), jdkVersion = arguments.jdkVersion, externalDocumentationLinks = parseLinks(arguments.links), noStdlibLink = arguments.noStdlibLink, - cacheRoot = arguments.cacheRoot, languageVersion = arguments.languageVersion, apiVersion = arguments.apiVersion, collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries, - noJdkLink = arguments.noJdkLink + noJdkLink = arguments.noJdkLink, + sourceRoots = sources.map(SourceRootImpl.Companion::parseSourceRoot), + analysisPlatform = sources.map (SourceRootImpl.Companion::parseSourceRoot).single().analysisPlatform, + samples = samples, + includes = includes, + moduleName = arguments.moduleName, + classpath = classPath + ) + + val config = DokkaConfigurationImpl( + outputDir = arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, + format = arguments.outputFormat, + impliedPlatforms = arguments.impliedPlatforms.split(','), + cacheRoot = arguments.cacheRoot, + + passesConfigurations = listOf( + passConfig + ) ) - val generator = DokkaGenerator( - DokkaConsoleLogger, - classPath, - sources.map(SourceRootImpl.Companion::parseSourceRoot), - samples, - includes, - arguments.moduleName, - documentationOptions) + val generator = DokkaGenerator(config, DokkaConsoleLogger) generator.generate() DokkaConsoleLogger.report() diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index ea55c8fe..78fd2d86 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -129,30 +129,33 @@ abstract class AbstractDokkaMojo : AbstractMojo() { return } - val gen = DokkaGenerator( - MavenDokkaLogger(log), - classpath, - sourceDirectories.map { SourceRootImpl(it) } + sourceRoots, - samplesDirs, - includeDirs + includes, - moduleName, - DocumentationOptions(getOutDir(), getOutFormat(), - sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) }, - jdkVersion = jdkVersion, - skipDeprecated = skipDeprecated, - skipEmptyPackages = skipEmptyPackages, - reportUndocumented = reportNotDocumented, - impliedPlatforms = impliedPlatforms, - perPackageOptions = perPackageOptions, - externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - cacheRoot = cacheRoot, - languageVersion = languageVersion, - apiVersion = apiVersion - ) + val passConfiguration = PassConfigurationImpl( + sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) }, + jdkVersion = jdkVersion, + skipDeprecated = skipDeprecated, + skipEmptyPackages = skipEmptyPackages, + reportUndocumented = reportNotDocumented, + perPackageOptions = perPackageOptions, + externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion + + ) + + val configuration = DokkaConfigurationImpl( + outputDir = getOutDir(), + format = getOutFormat(), + impliedPlatforms = impliedPlatforms, + cacheRoot = cacheRoot, + passesConfigurations = listOf( + passConfiguration + ) ) + val gen = DokkaGenerator(configuration, MavenDokkaLogger(log)) + gen.generate() } } -- cgit From ba09711a1ecbdaede86cab9e76d13ff1047f89b2 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Thu, 2 Aug 2018 18:59:20 +0300 Subject: ExternalDocumentationLinkResolver refactoring, extract common dependencies from guice modules --- core/src/main/kotlin/Generation/DokkaGenerator.kt | 11 +- .../Kotlin/ExternalDocumentationLinkResolver.kt | 114 ++++++++++++++------- core/src/main/kotlin/Utilities/DokkaModules.kt | 19 ++-- core/src/test/kotlin/TestAPI.kt | 19 +++- 4 files changed, 112 insertions(+), 51 deletions(-) (limited to 'core/src/main/kotlin/Utilities/DokkaModules.kt') diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 2e46d908..22d1519f 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule +import org.jetbrains.dokka.Utilities.DokkaRunModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -27,6 +28,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val logger: DokkaLogger) { private val documentationModules: MutableList = mutableListOf() + private val globalInjector = Guice.createInjector(DokkaRunModule(dokkaConfiguration)) fun generate() = with(dokkaConfiguration) { @@ -43,8 +45,9 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val timeBuild = measureTimeMillis { logger.info("Generating pages... ") - val outputInjector = Guice.createInjector(DokkaOutputModule(dokkaConfiguration, logger)) - outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) + val outputInjector = globalInjector.createChildInjector(DokkaOutputModule(dokkaConfiguration, logger)) + val instance = outputInjector.getInstance(Generator::class.java) + instance.buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } @@ -75,11 +78,11 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, } } - val injector = Guice.createInjector( + val injector = globalInjector.createChildInjector( DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> + documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> // FIXME: change to full graph visiting node.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), RefKind.Platform diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 2fc207b9..9d986aee 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -29,21 +29,14 @@ import kotlin.reflect.full.findAnnotation fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) } +typealias PackageFqNameToLocation = MutableMap + @Singleton -class ExternalDocumentationLinkResolver @Inject constructor( - val configuration: DokkaConfiguration, - val passConfiguration: DokkaConfiguration.PassConfiguration, - @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, - val logger: DokkaLogger +class PackageListProvider @Inject constructor( + val configuration: DokkaConfiguration, + val logger: DokkaLogger ) { - - val packageFqNameToLocation = mutableMapOf() - val formats = mutableMapOf() - - class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map) { - override fun toString(): String = rootUrl.toString() - } - + val storage = mutableMapOf() val cacheDir: Path? = when { configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") @@ -53,6 +46,25 @@ class ExternalDocumentationLinkResolver @Inject constructor( val cachedProtocols = setOf("http", "https", "ftp") + init { + for (conf in configuration.passesConfigurations) { + for (link in conf.externalDocumentationLinks) { + if (link in storage) { + continue + } + + try { + loadPackageList(link) + } catch (e: Exception) { + throw RuntimeException("Exception while loading package-list from $link", e) + } + } + + } + } + + + fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection { val connection = this.openConnection() connection.connectTimeout = timeout @@ -127,23 +139,23 @@ class ExternalDocumentationLinkResolver @Inject constructor( val (params, packages) = packageListStream - .bufferedReader() - .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } } + .bufferedReader() + .useLines { lines -> lines.partition { it.startsWith(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX) } } val paramsMap = params.asSequence() - .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) } - .groupBy({ (key, _) -> key }, { (_, value) -> value }) + .map { it.removePrefix(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX).split(":", limit = 2) } + .groupBy({ (key, _) -> key }, { (_, value) -> value }) val format = paramsMap["format"]?.singleOrNull() ?: "javadoc" val locations = paramsMap["location"].orEmpty() - .map { it.split("\u001f", limit = 2) } - .map { (key, value) -> key to value } - .toMap() + .map { it.split("\u001f", limit = 2) } + .map { (key, value) -> key to value } + .toMap() - val defaultResolverDesc = services["dokka-default"]!! - val resolverDesc = services[format] + val defaultResolverDesc = ExternalDocumentationLinkResolver.services["dokka-default"]!! + val resolverDesc = ExternalDocumentationLinkResolver.services[format] ?: defaultResolverDesc.takeIf { format in formatsWithDefaultResolver } ?: defaultResolverDesc.also { logger.warn("Couldn't find InboundExternalLinkResolutionService(format = `$format`) for $link, using Dokka default") @@ -160,16 +172,52 @@ class ExternalDocumentationLinkResolver @Inject constructor( val rootInfo = ExternalDocumentationRoot(link.url, resolver, locations) - packages.map { FqName(it) }.forEach { packageFqNameToLocation[it] = rootInfo } + val packageFqNameToLocation = mutableMapOf() + storage[link] = packageFqNameToLocation + + val fqNames = packages.map { FqName(it) } + for(name in fqNames) { + packageFqNameToLocation[name] = rootInfo + } + } + + + + class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map) { + override fun toString(): String = rootUrl.toString() } + companion object { + private val formatsWithDefaultResolver = + ServiceLocator + .allServices("format") + .filter { + val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor + desc?.generatorServiceClass == FileGenerator::class + }.map { it.name } + .toSet() + + } + +} + +class ExternalDocumentationLinkResolver @Inject constructor( + val configuration: DokkaConfiguration, + val passConfiguration: DokkaConfiguration.PassConfiguration, + @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, + val logger: DokkaLogger, + val packageListProvider: PackageListProvider +) { + + val formats = mutableMapOf() + val packageFqNameToLocation = mutableMapOf() + init { - passConfiguration.externalDocumentationLinks.forEach { - try { - loadPackageList(it) - } catch (e: Exception) { - throw RuntimeException("Exception while loading package-list from $it", e) - } + val fqNameToLocationMaps = passConfiguration.externalDocumentationLinks + .mapNotNull { packageListProvider.storage[it] } + + for(map in fqNameToLocationMaps) { + packageFqNameToLocation.putAll(map) } } @@ -198,14 +246,6 @@ class ExternalDocumentationLinkResolver @Inject constructor( companion object { const val DOKKA_PARAM_PREFIX = "\$dokka." val services = ServiceLocator.allServices("inbound-link-resolver").associateBy { it.name } - private val formatsWithDefaultResolver = - ServiceLocator - .allServices("format") - .filter { - val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor - desc?.generatorServiceClass == FileGenerator::class - }.map { it.name } - .toSet() } } diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 251d5c23..c2e652b6 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -1,8 +1,6 @@ package org.jetbrains.dokka.Utilities -import com.google.inject.Binder -import com.google.inject.Module -import com.google.inject.TypeLiteral +import com.google.inject.* import com.google.inject.binder.AnnotatedBindingBuilder import com.google.inject.name.Names import org.jetbrains.dokka.* @@ -13,6 +11,16 @@ import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" +class DokkaRunModule(val configuration: DokkaConfiguration) : Module { + override fun configure(binder: Binder) { + binder.bind().toInstance(configuration) + binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) + + binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) + } + +} + class DokkaAnalysisModule(val environment: AnalysisEnvironment, val configuration: DokkaConfiguration, val defaultPlatformsProvider: DefaultPlatformsProvider, @@ -29,7 +37,6 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(dokkaResolutionFacade) binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) - binder.bind().toInstance(configuration) binder.bind().toInstance(passConfiguration) binder.bind().toInstance(defaultPlatformsProvider) @@ -46,11 +53,7 @@ object StringListType : TypeLiteral<@JvmSuppressWildcards List>() class DokkaOutputModule(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) - - binder.bind().toInstance(configuration) binder.bind().toInstance(logger) - binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) val descriptor = ServiceLocator.lookup("format", configuration.format) diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index b65efbe9..8974bd0b 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* import org.jetbrains.dokka.Utilities.DokkaAnalysisModule +import org.jetbrains.dokka.Utilities.DokkaRunModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -117,8 +118,22 @@ fun appendDocumentation(documentation: DocumentationModule, val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms } - val injector = Guice.createInjector( - DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentation.nodeRefGraph, passConfiguration, DokkaConsoleLogger)) + + val globalInjector = Guice.createInjector( + DokkaRunModule(dokkaConfiguration) + ) + + val injector = globalInjector.createChildInjector( + DokkaAnalysisModule( + environment, + dokkaConfiguration, + defaultPlatformsProvider, + documentation.nodeRefGraph, + passConfiguration, + DokkaConsoleLogger + ) + ) + buildDocumentationModule(injector, documentation) Disposer.dispose(environment) } -- cgit