@@ -45,13 +45,11 @@ internal class SchemaClassScanner(
4545 private val typeDefinitions = allDefinitions.filterIsInstance<TypeDefinition <* >>()
4646 private val baseTypeNames = typeDefinitions.filter { it !is SDLExtensionDefinition }.map { it.name }.toSet()
4747
48- // the first extension of an undefined union, enum, interface or scalar stands in for its definition
4948 private val loneExtensions = typeDefinitions
5049 .filter { it is SDLExtensionDefinition && it !is ObjectTypeDefinition && it !is InputObjectTypeDefinition && it.name !in baseTypeNames }
5150 .distinctBy { it.name }
5251
5352 private val definitionsByName = typeDefinitions.filter { it !is SDLExtensionDefinition || it in loneExtensions }.associateBy { it.name }
54- // without extensions of a different kind than their type, which are ignored with a warning, see init
5553 private val typeExtensions: TypeExtensions = typeDefinitions
5654 .filter { it is SDLExtensionDefinition && it !in loneExtensions && ! extendsOtherKind(it) }
5755 .groupBy { it.name }
@@ -80,8 +78,6 @@ internal class SchemaClassScanner(
8078 log.warn(" Type '${extension.name} ' is defined as ${definition.kind()} , but extended as ${extension.kind()} . The extension is ignored." )
8179 }
8280
83- // Input object types never go into the type => class bimap that interface and union type resolution use, so several of
84- // them can share a class, e.g. ObjectNode
8581 initialDictionary
8682 .filterKeys { definitionsByName[it] !is InputObjectTypeDefinition }
8783 .entries.groupBy({ it.value }, { it.key })
@@ -397,8 +393,6 @@ internal class SchemaClassScanner(
397393 }
398394 }
399395
400- // Scanning a sealed subclass can find the classes of the other types, so only fail when no type has exactly one sealed
401- // subclass named after it. Types still without a class fail on the next pass.
402396 val sealedMatches = typesWithoutClass.filterIsInstance<ObjectTypeDefinition >().mapNotNull { sealedSubclassMatches(it).singleOrNull() }
403397 if (sealedMatches.isEmpty()) {
404398 typesWithoutClass.firstOrNull()?.let { throw SchemaClassScannerError (failureMessage(it) + sealedSubclassHint(it)) }
@@ -407,9 +401,6 @@ internal class SchemaClassScanner(
407401 sealedMatches.forEach { handleFoundType(it) }
408402 }
409403
410- /* *
411- * Explains why no sealed subclass was used for the type, if any of its unions or interfaces has a sealed class.
412- */
413404 private fun sealedSubclassHint (type : TypeDefinition <* >): String {
414405 if (type !is ObjectTypeDefinition ) {
415406 return " "
@@ -429,25 +420,15 @@ internal class SchemaClassScanner(
429420 }
430421 }
431422
432- /* *
433- * A member of a union or an implementor of an interface may never be returned directly, e.g. `NormalPet` when only
434- * `pets(): List<Pet>` returns `union Pet`. If the class found for the union or interface is sealed, its subclass named
435- * after the object type can be used instead.
436- */
437423 private fun sealedSubclassMatches (type : ObjectTypeDefinition ): List <TypeClassMatcher .ValidMatch > =
438424 sealedTypesOf(type)
439425 .flatMap { sealedType ->
440426 sealedSubclasses(sealedType.unwrap())
441427 .filter { it.simpleName == type.name }
442- .map { TypeClassMatcher .ValidMatch (type, parameterize (it, sealedType), SealedSubclassReference (sealedType)) }
428+ .map { TypeClassMatcher .ValidMatch (type, withSealedTypeArguments (it, sealedType), SealedSubclassReference (sealedType)) }
443429 }
444- // a subclass is found twice when it's under two of these sealed types, or extends both a sealed type and one of its
445- // sealed subclasses
446430 .distinctBy { it.javaType.unwrap() }
447431
448- /* *
449- * The sealed classes found for the unions the type is a member of and the interfaces it implements.
450- */
451432 private fun sealedTypesOf (type : ObjectTypeDefinition ): List <JavaType > =
452433 dictionary
453434 .filterKeys { definition ->
@@ -461,18 +442,11 @@ internal class SchemaClassScanner(
461442 .distinct()
462443 .filter { it.unwrap().kotlin.isSealed }
463444
464- /* *
465- * All subclasses of a sealed class, including those of its sealed subclasses. kotlin-reflect also returns the permitted
466- * subclasses of Java sealed classes.
467- */
445+ // kotlin-reflect also returns the permitted subclasses of Java sealed classes
468446 private fun sealedSubclasses (clazz : Class <* >): List <Class <* >> =
469447 clazz.kotlin.sealedSubclasses.flatMap { listOf (it.java) + sealedSubclasses(it.java) }
470448
471- /* *
472- * Passes the type arguments of a parameterized sealed class on to its generic subclass, e.g. `Success<Pet>` for
473- * `Result<Pet>`, so the types of the subclass's fields can be resolved.
474- */
475- private fun parameterize (subclass : Class <* >, sealedType : JavaType ): JavaType {
449+ private fun withSealedTypeArguments (subclass : Class <* >, sealedType : JavaType ): JavaType {
476450 if (sealedType !is ParameterizedType || subclass.typeParameters.isEmpty()) {
477451 return subclass
478452 }
@@ -538,7 +512,6 @@ internal class SchemaClassScanner(
538512 }
539513 }
540514
541- // a JDK dynamic proxy only implements its target's interfaces, so the target's own methods and fields can't be called on it
542515 // TODO throw a FieldResolverError instead in 15.0.0 (#868)
543516 private fun warnIfNotCallableOnResolver (type : ObjectTypeDefinition , fieldResolver : FieldResolver ) {
544517 val source = fieldResolver.search.source ? : return
@@ -693,7 +666,6 @@ internal class SchemaClassScanner(
693666 }
694667 }
695668
696- // e.g. `extend union Foo` of `type Foo`
697669 private fun extendsOtherKind (definition : TypeDefinition <* >): Boolean {
698670 val type = definitionsByName[definition.name]
699671 return definition is SDLExtensionDefinition && type != null && type.kind() != definition.kind()
0 commit comments