diff --git a/cpg-language-ini/src/main/kotlin/de/fraunhofer/aisec/cpg/frontend/configfiles/IniFileFrontend.kt b/cpg-language-ini/src/main/kotlin/de/fraunhofer/aisec/cpg/frontend/configfiles/IniFileFrontend.kt index 340f839806..c9b010d90b 100644 --- a/cpg-language-ini/src/main/kotlin/de/fraunhofer/aisec/cpg/frontend/configfiles/IniFileFrontend.kt +++ b/cpg-language-ini/src/main/kotlin/de/fraunhofer/aisec/cpg/frontend/configfiles/IniFileFrontend.kt @@ -26,12 +26,16 @@ package de.fraunhofer.aisec.cpg.frontend.configfiles import de.fraunhofer.aisec.cpg.TranslationContext +import de.fraunhofer.aisec.cpg.frontends.Handler import de.fraunhofer.aisec.cpg.frontends.Language import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend import de.fraunhofer.aisec.cpg.frontends.TranslationException import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration +import de.fraunhofer.aisec.cpg.graph.declarations.NamespaceDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal import de.fraunhofer.aisec.cpg.graph.types.Type import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation import de.fraunhofer.aisec.cpg.sarif.Region @@ -39,20 +43,19 @@ import java.io.File import java.io.FileInputStream import java.net.URI import org.ini4j.Ini -import org.ini4j.Profile +import org.ini4j.Profile.Section /** * The INI file frontend. This frontend utilizes the [ini4j library](https://ini4j.sourceforge.net/) * to parse the config file. The result consists of * - a [TranslationUnitDeclaration] wrapping the entire result - * - a [de.fraunhofer.aisec.cpg.graph.declarations.NamespaceDeclaration] wrapping the INI file and - * thus preventing collisions with other symbols which might have the same name + * - a [NamespaceDeclaration] wrapping the INI file and thus preventing collisions with other + * symbols which might have the same name * - a [RecordDeclaration] per `Section` (a section refers to a block of INI values marked with a * line `[SectionName]`) - * - a [de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration] per entry in a section. The - * [de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration.name] matches the `entry`s `name` - * field and the [de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration.initializer] is set - * to a [statements.expressions.Literal] with the corresponding `entry`s `value`. + * - a [FieldDeclaration] per entry in a section. The [FieldDeclaration.name] matches the `entry`s + * `name` field and the [FieldDeclaration.initializer] is set to a [Literal] with the + * corresponding `entry`s `value`. * * Note: * - the "ini4j" library does not provide any super type for all nodes. Thus, the frontend accepts @@ -63,8 +66,7 @@ import org.ini4j.Profile * `.toString()` * - [locationOf] always returns `null` as the "ini4j" library does not provide any means of getting * a location given a node - * - [setComment] not implemented as this is not used (no - * [de.fraunhofer.aisec.cpg.frontends.Handler] pattern implemented) + * - [setComment] not implemented as this is not used (no [Handler] pattern implemented) * - Comments in general are not supported. */ class IniFileFrontend(language: Language, ctx: TranslationContext) : @@ -116,7 +118,7 @@ class IniFileFrontend(language: Language, ctx: TranslationConte * Translates a `Section` into a [RecordDeclaration] and handles all `entries` using * [handleEntry]. */ - private fun handleSection(section: Profile.Section) { + private fun handleSection(section: Section) { val record = newRecordDeclaration(name = section.name, kind = "section", rawNode = section) scopeManager.addDeclaration(record) scopeManager.enterScope(record) @@ -125,10 +127,8 @@ class IniFileFrontend(language: Language, ctx: TranslationConte } /** - * Translates an `MutableEntry` to a new - * [de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration] with the - * [de.fraunhofer.aisec.cpg.graph.declarations.FieldDeclaration.initializer] being set to the - * `entry`s value. + * Translates an `MutableEntry` to a new [FieldDeclaration] with the + * [FieldDeclaration.initializer] being set to the `entry`s value. */ private fun handleEntry(entry: MutableMap.MutableEntry) { val field = @@ -141,8 +141,53 @@ class IniFileFrontend(language: Language, ctx: TranslationConte return primitiveType("string") } + /** + * Returns an approximation of the original code by re-creating (parts of) the INI file given + * the parsed results provided by ini4j. This is not a perfect representation of the original + * code (comments, order, ...), however re-parsing it should result in the same + * CPG-representation. + */ override fun codeOf(astNode: Any): String? { - return astNode.toString() + return when (astNode) { + is Ini -> codeOfIni(astNode) + is Section -> codeOfSection(astNode) + is Map.Entry<*, *> -> codeOfEntry(astNode) + else -> null + } + } + + /** + * Returns an approximation of the original code by re-creating (parts of) the INI file given + * the parsed results provided by ini4j. This is not a perfect representation of the original + * code (comments, order, ...), however re-parsing it should result in the same + * CPG-representation. + */ + private fun codeOfIni(ini: Ini): String { + return ini.values.joinToString(System.lineSeparator()) { codeOfSection(it) } + } + + /** + * Returns an approximation of the original code by re-creating (parts of) the INI file given + * the parsed results provided by ini4j. This is not a perfect representation of the original + * code (comments, order, ...), however re-parsing it should result in the same + * CPG-representation. + */ + private fun codeOfEntry(entry: Map.Entry<*, *>): String { + return "${entry.key} = ${entry.value}" + } + + /** + * Returns an approximation of the original code by re-creating (parts of) the INI file given + * the parsed results provided by ini4j. This is not a perfect representation of the original + * code (comments, order, ...), however re-parsing it should result in the same + * CPG-representation. + */ + private fun codeOfSection(section: Section): String { + return "[" + + section.name + + "]" + + System.lineSeparator() + + section.entries.joinToString(System.lineSeparator()) { codeOfEntry(it) } } /**