Fix tracking of known usages/subtypes (#1241)

Fixes an issue where known subtype/usage information is not gathered.

Also: change class RuntimeData to not return pairs for better composability.
This commit is contained in:
Daniel Chao
2025-10-16 12:48:35 -07:00
committed by GitHub
parent 91fec70668
commit b8aad85943
56 changed files with 522 additions and 85 deletions

View File

@@ -84,8 +84,8 @@ internal data class RuntimeData(
myRef: T,
versions: Set<String>?,
comparator: Comparator<String>,
): Pair<RuntimeData, Boolean> {
if (versions == null) return this to false
): RuntimeData {
if (versions == null) return this
val newEffectiveVersions = knownVersions.mapTo(mutableSetOf()) { it.text } + versions
val knownVersions =
newEffectiveVersions
@@ -93,9 +93,9 @@ internal data class RuntimeData(
.map { version -> RuntimeDataLink(text = version, href = myRef.pageUrlForVersion(version)) }
.toSet()
if (knownVersions == this.knownVersions) {
return this to false
return this
}
return copy(knownVersions = knownVersions) to true
return copy(knownVersions = knownVersions)
}
fun <T : ElementRef<*>> addKnownUsages(
@@ -103,8 +103,8 @@ internal data class RuntimeData(
refs: Collection<T>?,
text: (T) -> String,
comparator: Comparator<String>,
): Pair<RuntimeData, Boolean> {
if (refs == null) return this to false
): RuntimeData {
if (refs == null) return this
val newLinks =
refs.mapTo(mutableSetOf()) { ref ->
RuntimeDataLink(text = text(ref), href = ref.pageUrlRelativeTo(myRef))
@@ -112,27 +112,27 @@ internal data class RuntimeData(
val knownUsages =
(this.knownUsages + newLinks).distinctByCommparator(comparator).sortedBy { it.text }.toSet()
if (knownUsages == this.knownUsages) {
return this to false
return this
}
return copy(knownUsages = knownUsages) to true
return copy(knownUsages = knownUsages)
}
fun addKnownSubtypes(
myRef: TypeRef,
subtypes: Collection<TypeRef>?,
comparator: Comparator<String>,
): Pair<RuntimeData, Boolean> {
if (subtypes == null) return this to false
): RuntimeData {
if (subtypes == null) return this
val newLinks =
subtypes.mapTo(mutableSetOf()) { ref ->
RuntimeDataLink(text = ref.displayName, href = ref.pageUrlRelativeTo(myRef))
}
val knownSubtypes =
(this.knownUsages + newLinks).distinctByCommparator(comparator).sortedBy { it.text }.toSet()
(this.knownSubtypes + newLinks).distinctByCommparator(comparator).sortedBy { it.text }.toSet()
if (knownSubtypes == this.knownSubtypes) {
return this to false
return this
}
return copy(knownSubtypes = knownSubtypes) to true
return copy(knownSubtypes = knownSubtypes)
}
fun Collection<RuntimeDataLink>.distinctByCommparator(
@@ -156,5 +156,5 @@ internal data class RuntimeData(
fun perPackage(): RuntimeData = copy(knownUsages = setOf(), knownSubtypes = setOf())
fun perPackageVersion(): RuntimeData = RuntimeData(knownVersions = setOf())
fun perPackageVersion(): RuntimeData = copy(knownVersions = setOf())
}

View File

@@ -126,14 +126,10 @@ internal class RuntimeDataGenerator(
// we must not have this package in our docsite.
if (!runtimeDataPath.isRegularFile()) return@launch
val usages = packageUsages[ref]
val (data, hasNewData) =
ref.existingPerPackageVersionRuntimeData.addKnownUsages(
ref,
usages,
PackageRef::pkg,
descendingVersionComparator,
)
if (hasNewData) {
val existingData = ref.existingPerPackageVersionRuntimeData
val data =
existingData.addKnownUsages(ref, usages, PackageRef::pkg, descendingVersionComparator)
if (data != existingData) {
data.doWriteTo(outputDir.resolve(ref.perPackageVersionRuntimeDataPath))
}
}
@@ -172,7 +168,7 @@ internal class RuntimeDataGenerator(
private fun writePackageFile(packageData: PackageData) {
val ref = packageData.ref
val newVersions = packageVersions[packageData.ref.pkg]?.mapTo(mutableSetOf()) { it.version }
val (data, _) =
val data =
ref.existingPerPackageRuntimeData.addKnownVersions(
ref,
newVersions,
@@ -183,7 +179,7 @@ internal class RuntimeDataGenerator(
private fun writePackageFilePerVersion(packageData: PackageData) {
val ref = packageData.ref
val (data, _) =
val data =
ref.existingPerPackageVersionRuntimeData.addKnownUsages(
ref,
packageUsages[ref],
@@ -196,7 +192,7 @@ internal class RuntimeDataGenerator(
private fun writeClassFile(classData: ClassData) {
val ref = classData.ref
val newVersions = classVersions[ref.id]?.mapTo(mutableSetOf()) { it }
val (data, _) =
val data =
ref.existingPerPackageRuntimeData.addKnownVersions(
ref,
newVersions,
@@ -208,12 +204,11 @@ internal class RuntimeDataGenerator(
private fun writeClassFilePerVersion(classData: ClassData) {
val ref = classData.ref
val newSubtypes = subtypes[ref]
val (data, _) =
ref.existingPerPackageVersionRuntimeData.addKnownSubtypes(
ref,
newSubtypes,
descendingVersionComparator,
)
val newUsages = typeUsages[ref]
val data =
ref.existingPerPackageVersionRuntimeData
.addKnownSubtypes(ref, newSubtypes, descendingVersionComparator)
.addKnownUsages(ref, newUsages, TypeRef::displayName, descendingVersionComparator)
data.writePerPackageVersion(ref)
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "moduleExtend",
"href": "../moduleExtend/index.html"
}
]
}

View File

@@ -1 +1,16 @@
{}
{
"knownSubtypes": [
{
"text": "MyClass2",
"href": "MyClass2.html"
},
{
"text": "MyClass3",
"href": "MyClass3.html"
},
{
"text": "MyClass4",
"href": "MyClass4.html"
}
]
}

View File

@@ -1 +1,12 @@
{}
{
"knownSubtypes": [
{
"text": "MyClass3",
"href": "MyClass3.html"
},
{
"text": "MyClass4",
"href": "MyClass4.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "TypeReferences.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "TypeReferences.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "Person1",
"href": "Person1.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "moduleMethodCommentInheritance",
"href": "../moduleMethodCommentInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "moduleMethodTypeReferences",
"href": "index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "UserDefinedAnnotation1",
"href": "UserDefinedAnnotation1.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "modulePropertyCommentInheritance",
"href": "../modulePropertyCommentInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "modulePropertyTypeReferences",
"href": "index.html"
}
]
}

View File

@@ -1 +1,12 @@
{}
{
"knownUsages": [
{
"text": "Foo",
"href": "../moduleTypes2/Foo.html"
},
{
"text": "moduleTypes2",
"href": "../moduleTypes2/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "Foo",
"href": "Foo.html"
}
]
}

View File

@@ -1 +1,16 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "../classMethodTypeReferences/TypeReferences.html"
},
{
"text": "moduleMethodTypeReferences",
"href": "../moduleMethodTypeReferences/index.html"
},
{
"text": "modulePropertyTypeReferences",
"href": "../modulePropertyTypeReferences/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "Person2",
"href": "../typeAliasInheritance/Person2.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "typeAliasInheritance",
"href": "../typeAliasInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "com.package1",
"href": "../../com.package1/1.2.3/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "moduleExtend",
"href": "../moduleExtend/index.html"
}
]
}

View File

@@ -1 +1,16 @@
{}
{
"knownSubtypes": [
{
"text": "MyClass2",
"href": "MyClass2.html"
},
{
"text": "MyClass3",
"href": "MyClass3.html"
},
{
"text": "MyClass4",
"href": "MyClass4.html"
}
]
}

View File

@@ -1 +1,12 @@
{}
{
"knownSubtypes": [
{
"text": "MyClass3",
"href": "MyClass3.html"
},
{
"text": "MyClass4",
"href": "MyClass4.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "TypeReferences.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "TypeReferences.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "Person1",
"href": "Person1.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "moduleMethodCommentInheritance",
"href": "../moduleMethodCommentInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "moduleMethodTypeReferences",
"href": "index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "UserDefinedAnnotation1",
"href": "UserDefinedAnnotation1.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "modulePropertyCommentInheritance",
"href": "../modulePropertyCommentInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "modulePropertyTypeReferences",
"href": "index.html"
}
]
}

View File

@@ -1 +1,12 @@
{}
{
"knownUsages": [
{
"text": "Foo",
"href": "../moduleTypes2/Foo.html"
},
{
"text": "moduleTypes2",
"href": "../moduleTypes2/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "Foo",
"href": "Foo.html"
}
]
}

View File

@@ -1 +1,16 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "../classMethodTypeReferences/TypeReferences.html"
},
{
"text": "moduleMethodTypeReferences",
"href": "../moduleMethodTypeReferences/index.html"
},
{
"text": "modulePropertyTypeReferences",
"href": "../modulePropertyTypeReferences/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "Person2",
"href": "../typeAliasInheritance/Person2.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "typeAliasInheritance",
"href": "../typeAliasInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "com.package1",
"href": "../../com.package1/1.2.3/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "moduleExtend",
"href": "../moduleExtend/index.html"
}
]
}

View File

@@ -1 +1,16 @@
{}
{
"knownSubtypes": [
{
"text": "MyClass2",
"href": "MyClass2.html"
},
{
"text": "MyClass3",
"href": "MyClass3.html"
},
{
"text": "MyClass4",
"href": "MyClass4.html"
}
]
}

View File

@@ -1 +1,12 @@
{}
{
"knownSubtypes": [
{
"text": "MyClass3",
"href": "MyClass3.html"
},
{
"text": "MyClass4",
"href": "MyClass4.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "TypeReferences.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "TypeReferences.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "Person1",
"href": "Person1.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "moduleMethodCommentInheritance",
"href": "../moduleMethodCommentInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "moduleMethodTypeReferences",
"href": "index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "UserDefinedAnnotation1",
"href": "UserDefinedAnnotation1.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "modulePropertyCommentInheritance",
"href": "../modulePropertyCommentInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "modulePropertyTypeReferences",
"href": "index.html"
}
]
}

View File

@@ -1 +1,12 @@
{}
{
"knownUsages": [
{
"text": "Foo",
"href": "../moduleTypes2/Foo.html"
},
{
"text": "moduleTypes2",
"href": "../moduleTypes2/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "Foo",
"href": "Foo.html"
}
]
}

View File

@@ -1 +1,20 @@
{}
{
"knownUsages": [
{
"text": "TypeReferences",
"href": "../classMethodTypeReferences/TypeReferences.html"
},
{
"text": "TypeReferences",
"href": "../classPropertyTypeReferences/TypeReferences.html"
},
{
"text": "moduleMethodTypeReferences",
"href": "../moduleMethodTypeReferences/index.html"
},
{
"text": "modulePropertyTypeReferences",
"href": "../modulePropertyTypeReferences/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "Person2",
"href": "../typeAliasInheritance/Person2.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownSubtypes": [
{
"text": "typeAliasInheritance",
"href": "../typeAliasInheritance/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "ternalPackage",
"href": "../../../com.package1/1.2.3/ternalPackage/index.html"
}
]
}

View File

@@ -1 +1,8 @@
{}
{
"knownUsages": [
{
"text": "com.package1",
"href": "../../com.package1/1.2.3/index.html"
}
]
}

View File

@@ -147,6 +147,8 @@ class CliDocGeneratorTest {
assertThat(e).hasMessageContaining("at least one", "module")
}
// to re-generate output, delete directory pkl-doc/src/test/files/DocGeneratorTest/output and run
// again
@ParameterizedTest
@MethodSource("generateDocs")
fun test(relativeFilePath: String) {

View File

@@ -41,7 +41,7 @@ class RuntimeDataTest {
ModuleRef(pkg = "foo", pkgUri = null, version = "1.3.0", module = "foo"),
)
val result = current.addKnownUsages(ref, usages, { it.fullName }, descendingVersionComparator)
assertThat(result.first)
assertThat(result)
.isEqualTo(
RuntimeData(
knownUsages = setOf(RuntimeDataLink("foo.foo", "../../../foo/1.3.0/foo/index.html"))
@@ -59,7 +59,7 @@ class RuntimeDataTest {
val usages = setOf(ModuleRef(pkg = "foo", pkgUri = null, version = "1.2.0", module = "foo"))
val result = current.addKnownUsages(ref, usages, { it.fullName }, descendingVersionComparator)
assertThat(result.first)
assertThat(result)
.isEqualTo(
RuntimeData(
knownUsages = setOf(RuntimeDataLink("foo.foo", "../../../foo/1.3.0/foo/index.html"))