Skip to content

Commit

Permalink
fix: Fix parent class of generated VSS specifications
Browse files Browse the repository at this point in the history
The parent is now correctly parsed from sub classes which do not match
the file name.
  • Loading branch information
Chrylo committed Feb 7, 2024
1 parent 4f5eef6 commit f481f64
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ val VssSpecification.parentKey: String
return keys[keys.size - 2]
}

/**
* Similar to the [variableName] but for the parent and does not lowercase the [name] wherever necessary.
*/
val VssSpecification.parentClassName: String
get() {
if (parentKey.isEmpty()) return ""

return (classNamePrefix + parentKey).toCamelCase.replaceFirstChar { it.uppercase() }
}

/**
* Iterates through all nested children which also may have children and aggregates them into one big collection.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.writeTo
import org.eclipse.kuksa.vsscore.annotation.VssDefinition
import org.eclipse.kuksa.vsscore.model.VssNode
import org.eclipse.kuksa.vsscore.model.parentClassName
import org.eclipse.kuksa.vssprocessor.parser.YamlDefinitionParser
import org.eclipse.kuksa.vssprocessor.spec.VssPath
import org.eclipse.kuksa.vssprocessor.spec.VssSpecificationSpecModel
Expand Down Expand Up @@ -115,6 +116,7 @@ class VssDefinitionProcessor(

logger.info("Ambiguous specifications - Generate nested classes: $duplicateSpecificationNames")

val generatedFilesVssPathToClassName = mutableMapOf<String, String>()
for ((vssPath, specModel) in vssPathToSpecification) {
// Every duplicate is produced as a nested class - No separate file should be generated
if (duplicateSpecificationNames.contains(vssPath.leaf)) {
Expand All @@ -128,11 +130,50 @@ class VssDefinitionProcessor(
duplicateSpecificationNames,
)

val file = FileSpec.builder(PACKAGE_NAME, classSpec.name!!)
val className = classSpec.name ?: throw NoSuchFieldException("")
val fileSpecBuilder = FileSpec.builder(PACKAGE_NAME, className)

val parentImport = createParentImport(specModel, generatedFilesVssPathToClassName)
if (parentImport.isNotEmpty()) {
fileSpecBuilder.addImport(PACKAGE_NAME, parentImport)
}

val file = fileSpecBuilder
.addType(classSpec)
.build()

file.writeTo(codeGenerator, false)
generatedFilesVssPathToClassName[vssPath.path] = className
}
}

// Uses a map of vssPaths to ClassNames which are validated if it contains a parent of the given specModel.
// If the actual parent is a sub class (Driver) in another class file (e.g. Vehicle) then this method returns
// a sub import e.g. "Vehicle.Driver". Otherwise just "Vehicle" is returned.
private fun createParentImport(
specModel: VssSpecificationSpecModel,
parentVssPathToClassName: Map<String, String>,
): String {
var availableParentVssPath = specModel.vssPath
var parentSpecClassName: String? = null

// Iterate up from the parent until the actual file name = class name was found. This indicates
// that the actual parent is a sub class in this file.
while (availableParentVssPath.contains(".")) {
availableParentVssPath = availableParentVssPath.substringBeforeLast(".")

parentSpecClassName = parentVssPathToClassName[availableParentVssPath]
if (parentSpecClassName != null) break
}

if (parentSpecClassName == null) return ""

val parentClassName = specModel.parentClassName

return if (parentSpecClassName != parentClassName) {
"$parentSpecClassName.$parentClassName" // Sub class in another file
} else {
parentClassName // Main class = File name
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import org.eclipse.kuksa.vsscore.model.VssProperty
import org.eclipse.kuksa.vsscore.model.VssSpecification
import org.eclipse.kuksa.vsscore.model.className
import org.eclipse.kuksa.vsscore.model.name
import org.eclipse.kuksa.vsscore.model.parentClassName
import org.eclipse.kuksa.vsscore.model.parentKey
import org.eclipse.kuksa.vsscore.model.variableName
import kotlin.reflect.KClass
Expand Down Expand Up @@ -152,6 +153,7 @@ internal class VssSpecificationSpecModel(
relevantRelatedSpecifications,
nestedClasses,
)

nestedChildSpecs.add(childSpec)
}

Expand Down Expand Up @@ -274,13 +276,14 @@ internal class VssSpecificationSpecModel(
}

fun createParentSpec(memberName: String, memberType: TypeName): PropertySpec {
val parentClass = if (parentClassName.isNotEmpty()) "$parentClassName::class" else "null"
return PropertySpec
.builder(memberName, memberType)
.mutable(false)
.addModifiers(KModifier.OVERRIDE)
.getter(
FunSpec.getterBuilder()
.addStatement("return %L", "$className::class")
.addStatement("return %L", parentClass)
.build(),
)
.build()
Expand Down

0 comments on commit f481f64

Please sign in to comment.