Skip to content

Commit

Permalink
Merge pull request #547 from smeup/feature/LS24002977/i-specs-externa…
Browse files Browse the repository at this point in the history
…l-fields-renaming

Feature/ls24002977/i specs external fields renaming
  • Loading branch information
lanarimarco authored Jun 18, 2024
2 parents 8429ca2 + d004d20 commit 41c0941
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.smeup.rpgparser.parsing.parsetreetoast

import com.smeup.rpgparser.RpgParser
import com.strumenta.kolasu.mapping.toPosition
import com.strumenta.kolasu.model.Position
import kotlinx.serialization.Serializable

@Serializable
sealed class InputSpecification

@Serializable
data class FileNameInputSpecification(
val name: String,
val position: Position?
) : InputSpecification()

@Serializable
data class ExternalFieldInputSpecification(
val originalName: String,
val newName: String,
val controlLevelIndicator: String?,
val matchingFieldsIndicator: String?,
val position: Position?
) : InputSpecification()

/**
* Links the external definition to its specifications.
*/
data class InputSpecificationGroup(
val fileName: FileNameInputSpecification,
val specifications: List<InputSpecification>
)

fun RpgParser.ControlLevelIndicatorContext.toIndicator(): String? {
return when {
this.ControlLevelIndicator() != null -> this.ControlLevelIndicator().text
else -> null
}
}

fun RpgParser.MatchingFieldsIndicatorContext.toIndicator(): String? {
return when {
this.MatchingRecordIndicator() != null -> this.MatchingRecordIndicator().text
else -> null
}
}

fun RpgParser.Is_external_fieldContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()): InputSpecification {
val originalName = this.IF_Name().text.trim()
val newName = this.IF_FieldName().text.trim()
val controlIndicator = this.controlLevelIndicator().toIndicator()
val matchField = this.matchingFieldsIndicator().toIndicator()

// TODO: Add result indicators
// val resultIndicators = this.resultIndicator()

return ExternalFieldInputSpecification(
originalName,
newName,
controlIndicator,
matchField,
toPosition(conf.considerPosition)
)
}

fun RpgParser.Ispec_fixedContext.toAst(conf: ToAstConfiguration = ToAstConfiguration()): InputSpecification {
return when {
this.is_external_field() != null -> this.is_external_field().toAst(conf)
this.IS_FileName() != null -> {
val fileName = this.IS_FileName().text.trim()

// TODO: Add support for indicators
FileNameInputSpecification(
fileName,
toPosition(conf.considerPosition)
)
}
else -> todo(conf = conf)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import java.util.*

enum class AstHandlingPhase {
FileDefinitionsCreation,
InputSpecificationsCreation,
DataDefinitionsCreation,
MainStatementsCreation,
SubroutinesCreation,
Expand Down Expand Up @@ -95,6 +96,7 @@ typealias KnownDataDefinitionInstance = MutableMap<String, DataDefinition>
private fun List<StatementContext?>.getDataDefinition(
conf: ToAstConfiguration = ToAstConfiguration(),
fileDefinitions: Map<FileDefinition, List<DataDefinition>>? = null,
inputSpecifications: List<InputSpecificationGroup> = emptyList(),
parentDataDefinitions: List<DataDefinition>? = null,
useKnownDataDefinitionInstance: Boolean = false
): Pair<MutableList<DataDefinitionProvider>, KnownDataDefinitionInstance> {
Expand All @@ -105,7 +107,8 @@ private fun List<StatementContext?>.getDataDefinition(
val knownDataDefinitions = if (useKnownDataDefinitionInstance) KnownDataDefinition.getInstance() else mutableMapOf()

fileDefinitions?.let {
it.values.flatten().toList().removeDuplicatedDataDefinition().forEach { def ->
val postProcessedFileDefinitions = it.processWithSpecifications(inputSpecifications)
postProcessedFileDefinitions.values.flatten().removeDuplicatedDataDefinition().forEach { def ->
dataDefinitionProviders.add(def.updateKnownDataDefinitionsAndGetHolder(knownDataDefinitions))
}
}
Expand Down Expand Up @@ -151,11 +154,13 @@ private fun List<StatementContext?>.getDataDefinition(

private fun RContext.getDataDefinitions(
conf: ToAstConfiguration = ToAstConfiguration(),
fileDefinitions: Map<FileDefinition, List<DataDefinition>>
fileDefinitions: Map<FileDefinition, List<DataDefinition>>,
inputSpecifications: List<InputSpecificationGroup> = emptyList()
): List<DataDefinition> {
val (providers) = this.statement().getDataDefinition(
conf = conf,
fileDefinitions = fileDefinitions,
inputSpecifications = inputSpecifications,
useKnownDataDefinitionInstance = true
)
return providers.mapNotNull { kotlin.runCatching { it.toDataDefinition() }.getOrNull() }
Expand Down Expand Up @@ -264,7 +269,12 @@ fun RContext.toAst(conf: ToAstConfiguration = ToAstConfiguration(), source: Stri
}.toMap()
checkAstCreationErrors(phase = AstHandlingPhase.FileDefinitionsCreation)

val dataDefinitions = getDataDefinitions(conf, fileDefinitions)
val inputSpecifications = this.findAllDescendants(Ispec_fixedContext::class).mapNotNull {
it.runParserRuleContext(conf) { context -> kotlin.runCatching { context.toAst(conf) }.getOrNull() }
}
checkAstCreationErrors(phase = AstHandlingPhase.InputSpecificationsCreation)

val dataDefinitions = getDataDefinitions(conf, fileDefinitions, inputSpecifications.grouped())
checkAstCreationErrors(phase = AstHandlingPhase.DataDefinitionsCreation)

val displayFiles = fileDefinitions.keys.toList().toDSPF()
Expand Down Expand Up @@ -2227,4 +2237,46 @@ private fun <T : AbstractDataDefinition> List<T>.removeUnnecessaryRecordFormat()
}
}

private fun List<DataDefinition>.renameFields(externalFieldSpecs: List<ExternalFieldInputSpecification>): List<DataDefinition> {
return this.map {
val match = externalFieldSpecs.find { spec -> spec.originalName == it.name }
match ?: return@map it
it.copy(name = match.newName)
}
}

private fun List<InputSpecification>.grouped(): List<InputSpecificationGroup> {
if (this.isEmpty()) return emptyList()
val files = this.withIndex().filter { it.value is FileNameInputSpecification }
val output: MutableList<InputSpecificationGroup> = ArrayList<InputSpecificationGroup>(files.size)

var lastFile = files.first()
fun addGroup(index: Int) {
val nestedSpecifications = this.slice(lastFile.index + 1 until index)
val group = InputSpecificationGroup(lastFile.value as FileNameInputSpecification, nestedSpecifications)
output.add(group)
}

files.slice(1..files.lastIndex).forEach {
addGroup(it.index)
lastFile = it
}

// Last pass if necessary
if (output.size < files.size) addGroup(this.size)

return output
}

private fun Map<FileDefinition, List<DataDefinition>>.processWithSpecifications(specifications: List<InputSpecificationGroup>): Map<FileDefinition, List<DataDefinition>> {
val buffer = this.toMutableMap()
specifications.forEach {
val target = buffer.entries.firstOrNull { entry -> (entry.key.internalFormatName ?: entry.key.name) == it.fileName.name }
target ?: error("No FileDefinition named ${it.fileName.name}")
val externalFieldSpecifications = it.specifications.filterIsInstance<ExternalFieldInputSpecification>()
buffer[target.key] = target.value.renameFields(externalFieldSpecifications)
}
return buffer
}

private fun String.isStringLiteral(): Boolean = startsWith('\'') && endsWith('\'')
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,14 @@ open class MULANGT50FileAccess1Test : MULANGTTest() {
val expected = listOf("Test")
assertEquals(expected, "smeup/MU500802".outputOf(configuration = smeupConfig))
}

/**
* I-Spec definitions on a renamed file definition
* @see #LS24002977
*/
@Test
fun executeMU500901() {
val expected = listOf("TSSYST(IBMI) TSLIBR() TSFILE() TATIPO(3) TBPROG(MULANGT12) AAAAAA(A03) BBBBBB(P01) CCCCCC()")
assertEquals(expected, "smeup/MU500901".outputOf(configuration = smeupConfig))
}
}
77 changes: 77 additions & 0 deletions rpgJavaInterpreter-core/src/test/resources/smeup/MU500901.rpgle
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
*====================================================================
* smeup V6R1.023DV
* Nome sorgente : MU500901
* Sorgente di origine : QTEMP/SRC(MU500901)
* Esportato il : 20240612 092228
*====================================================================
V* ==============================================================
V* MODIFICHE Ril. T Au Descrizione
V* gg/mm/aa nn.mm i xx Breve descrizione
V* ==============================================================
V* 29/05/24 MUTEST GUAGIA Creazione
V*=====================================================================
O * OBIETTIVO
O * Test atomico LIKE, OCCURS
V* ==============================================================
FMULANGTL IF E K DISK
F RENAME(MULANGR:MULANG3)
* -------------------------------------------------------------
/COPY QILEGEN,MULANG_D_D
/COPY QILEGEN,£TABB£1DS
/COPY QILEGEN,£PDS
IMULANG3
I MLSYST TSSYST
I MLLIBR TSLIBR
I MLFILE TSFILE
I MLTIPO TATIPO
I MLPROG TBPROG
I MLPSEZ AAAAAA
I MLPPAS BBBBBB
I MLPDES CCCCCC
*---------------------------------------------------------------------
RD* M A I N
*---------------------------------------------------------------------
C EVAL £DBG_Pgm = 'MU500901'
C EVAL £DBG_Sez = 'A09'
C EVAL £DBG_Fun = '*INZ'
C EXSR £DBG
C EXSR SEZ_A09
C EXSR £DBG
C EVAL £DBG_Fun = '*END'
C EXSR £DBG
C SETON LR
*---------------------------------------------------------------------
RD* Test atomico
*---------------------------------------------------------------------
C SEZ_A09 BEGSR
OA* A£.CDOP()
D* Test atomico specifiche I
C EVAL £DBG_Pas='P01'
*
C TSLANG5K KLIST
C KFLD TSSYST
C KFLD TATIPO
C KFLD TBPROG
C KFLD AAAAAA
C KFLD BBBBBB
C EVAL TSSYST='IBMI'
C EVAL TATIPO='3'
C EVAL TBPROG='MULANGT12'
C EVAL AAAAAA='A03'
C EVAL BBBBBB='P01'
*
C EVAL £DBG_Str=''
C TSLANG5K SETLL MULANGTL
C READ MULANG3
*
C EVAL £DBG_Str='TSSYST(' + %TRIM(TSSYST) +
C ') TSLIBR(' + %TRIM(TSLIBR) +
C ') TSFILE(' + %TRIM(TSFILE) +
C ') TATIPO(' + %TRIM(TATIPO) +
C ') TBPROG(' + %TRIM(TBPROG) +
C ') AAAAAA(' + %TRIM(AAAAAA) +
C ') BBBBBB(' + %TRIM(BBBBBB) +
C ') CCCCCC(' + %TRIM(CCCCCC) + ')'
C ENDSR
*---------------------------------------------------------------------
/COPY QILEGEN,MULANG_D_C

0 comments on commit 41c0941

Please sign in to comment.