From f9a44409e246d7a39587cdce562a9b49d777cf4d Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 21 Jan 2024 21:31:13 +0100 Subject: [PATCH 01/24] build: upgrade core 1.3.4 -> 1.3.5-rc3 --- plugin/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 649c73e45..ba72ff986 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -47,7 +47,7 @@ sourceSets { } dependencies { - implementation("ch.kleis.lcaac:core:1.3.4") + implementation("ch.kleis.lcaac:core:1.3.5-rc-3") implementation(files(layout.buildDirectory.dir("stdlib/ef3.1")) { builtBy("generateEmissionFactors31") From 2ee4c95e709c508f45f19bccd2329f5863284f45 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 21 Jan 2024 22:34:15 +0100 Subject: [PATCH 02/24] make it compile, 1.3.5-rc3 -> 1.4-rc --- plugin/build.gradle.kts | 2 +- .../lcaac/plugin/actions/ActionHelper.kt | 6 ++- .../ContributionAnalysisWithDataAction.kt | 4 +- .../lcaac/plugin/actions/csv/CsvProcessor.kt | 6 ++- .../actions/tasks/SensitivityAnalysisTask.kt | 12 ++++-- .../lcaac/plugin/language/loader/LcaMapper.kt | 39 +++++++++++-------- .../lcaac/plugin/testing/LcaTestRunner.kt | 19 +++++---- 7 files changed, 58 insertions(+), 30 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index ba72ff986..efd897bf7 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -47,7 +47,7 @@ sourceSets { } dependencies { - implementation("ch.kleis.lcaac:core:1.3.5-rc-3") + implementation("ch.kleis.lcaac:core:1.4-rc") implementation(files(layout.buildDirectory.dir("stdlib/ef3.1")) { builtBy("generateEmissionFactors31") diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ActionHelper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ActionHelper.kt index 75ce47eb4..ebeb21e92 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ActionHelper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ActionHelper.kt @@ -1,5 +1,6 @@ package ch.kleis.lcaac.plugin.actions +import ch.kleis.lcaac.core.datasource.CsvSourceOperations import ch.kleis.lcaac.core.lang.evaluator.EvaluationTrace import ch.kleis.lcaac.core.lang.evaluator.Evaluator import ch.kleis.lcaac.core.math.QuantityOperations @@ -8,6 +9,7 @@ import ch.kleis.lcaac.plugin.language.loader.LcaLoader import ch.kleis.lcaac.plugin.language.psi.LcaFile import com.intellij.openapi.application.runReadAction import com.intellij.openapi.progress.ProgressIndicator +import kotlin.io.path.Path fun traceSystemWithIndicator( indicator: ProgressIndicator, @@ -29,5 +31,7 @@ fun traceSystemWithIndicator( // compute indicator.text = "Solving system" val template = symbolTable.getTemplate(processName, matchLabels)!! // We are called from a process, so it must exist - return Evaluator(symbolTable, ops).trace(template) + val projectFile = Path(file.project.basePath!!).toFile() + val sourceOps = CsvSourceOperations(projectFile, ops) + return Evaluator(symbolTable, ops, sourceOps).trace(template) } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ContributionAnalysisWithDataAction.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ContributionAnalysisWithDataAction.kt index 902d5ef0c..69024566c 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ContributionAnalysisWithDataAction.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/ContributionAnalysisWithDataAction.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.Task import com.intellij.openapi.vfs.VirtualFileManager +import java.io.File import java.io.FileNotFoundException import kotlin.io.path.Path @@ -39,6 +40,7 @@ class ContributionAnalysisWithDataAction( override fun actionPerformed(e: AnActionEvent) { val project = e.project ?: return + val projectPath = project.basePath?.let { File(it) } ?: return val file = e.getData(LangDataKeys.PSI_FILE) as LcaFile? ?: return val containingDirectory = file.containingDirectory ?: return @@ -60,7 +62,7 @@ class ContributionAnalysisWithDataAction( val parser = LcaLoader(collector.collect(file), BasicOperations) parser.load() } - val csvProcessor = CsvProcessor(symbolTable) + val csvProcessor = CsvProcessor(projectPath, symbolTable) val results = requests.flatMap { request -> ProgressManager.checkCanceled() indicator.text = "Processing using ${request.arguments()}" diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessor.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessor.kt index 4af56e426..e8c7fd498 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessor.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessor.kt @@ -1,19 +1,23 @@ package ch.kleis.lcaac.plugin.actions.csv import ch.kleis.lcaac.core.assessment.ContributionAnalysisProgram +import ch.kleis.lcaac.core.datasource.CsvSourceOperations import ch.kleis.lcaac.core.lang.SymbolTable import ch.kleis.lcaac.core.lang.evaluator.Evaluator import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException import ch.kleis.lcaac.core.lang.expression.* import ch.kleis.lcaac.core.math.basic.BasicNumber import ch.kleis.lcaac.core.math.basic.BasicOperations +import java.io.File import java.lang.Double.parseDouble class CsvProcessor( + private val rootPath: File, private val symbolTable: SymbolTable, ) { private val ops = BasicOperations - private val evaluator = Evaluator(symbolTable, ops) + private val sourceOps = CsvSourceOperations(rootPath, ops) + private val evaluator = Evaluator(symbolTable, ops, sourceOps) fun process(request: CsvRequest): List { val reqName = request.processName diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/tasks/SensitivityAnalysisTask.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/tasks/SensitivityAnalysisTask.kt index 20b442cd7..85f0acf88 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/tasks/SensitivityAnalysisTask.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/actions/tasks/SensitivityAnalysisTask.kt @@ -4,6 +4,8 @@ import arrow.core.filterIsInstance import ch.kleis.lcaac.core.ParameterName import ch.kleis.lcaac.core.assessment.SensitivityAnalysis import ch.kleis.lcaac.core.assessment.SensitivityAnalysisProgram +import ch.kleis.lcaac.core.datasource.CsvSourceOperations +import ch.kleis.lcaac.core.datasource.DataSourceOperations import ch.kleis.lcaac.core.lang.SymbolTable import ch.kleis.lcaac.core.lang.evaluator.Evaluator import ch.kleis.lcaac.core.lang.evaluator.ToValue @@ -30,6 +32,7 @@ import com.intellij.openapi.progress.Task import com.intellij.openapi.project.Project import com.intellij.openapi.wm.ToolWindowManager import com.intellij.ui.content.ContentFactory +import java.io.File class SensitivityAnalysisTask( project: Project, @@ -85,8 +88,10 @@ class SensitivityAnalysisTask( processName, matchLabels )!! // We are called from a process, so it must exist - val (arguments, parameters) = prepareArguments(ops, symbolTable, template.params) - val trace = Evaluator(symbolTable, ops).trace(template, arguments) + val sourceOps = CsvSourceOperations(File(project.basePath!!), ops) + val (arguments, parameters) = + prepareArguments(ops, sourceOps, symbolTable, template.params) + val trace = Evaluator(symbolTable, ops, sourceOps).trace(template, arguments) this.analysis = SensitivityAnalysisProgram(trace.getSystemValue(), trace.getEntryPoint(), parameters).run() } @@ -123,10 +128,11 @@ class SensitivityAnalysisTask( private fun prepareArguments( ops: DualOperations, + sourceOps: DataSourceOperations, symbolTable: SymbolTable, params: Map> ): Pair>, ParameterVector> { - val dataReducer = DataExpressionReducer(symbolTable.data, ops) + val dataReducer = DataExpressionReducer(symbolTable.data, symbolTable.dataSources, ops, sourceOps) val reduced = params.mapValues { dataReducer.reduce(it.value) } val quantitativeArgumentList = reduced.filterIsInstance>() .toList() diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt index 31bc98dbb..3def4e099 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt @@ -1,6 +1,6 @@ package ch.kleis.lcaac.plugin.language.loader -import ch.kleis.lcaac.core.lang.* +import ch.kleis.lcaac.core.lang.SymbolTable import ch.kleis.lcaac.core.lang.dimension.Dimension import ch.kleis.lcaac.core.lang.dimension.UnitSymbol import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException @@ -42,9 +42,10 @@ class LcaMapper( val params = psiProcess.getParameters().mapValues { dataExpression(it.value) } val symbolTable = SymbolTable( data = try { - Register(globals - .plus(params.mapKeys { DataKey(it.key) }) - .plus(locals.mapKeys { DataKey(it.key) }) + Register( + globals + .plus(params.mapKeys { DataKey(it.key) }) + .plus(locals.mapKeys { DataKey(it.key) }) ) } catch (e: RegisterException) { throw EvaluatorException("Conflict between local variable(s) ${e.duplicates} and a global definition.") @@ -116,10 +117,12 @@ class LcaMapper( ) - private fun impact(exchange: LcaImpactExchange): EImpact { - return EImpact( - dataExpression(exchange.dataExpression), - indicatorSpec(exchange.indicatorRef), + private fun impact(exchange: LcaImpactExchange): ImpactBlock { + return EImpactBlockEntry( + EImpact( + dataExpression(exchange.dataExpression), + indicatorSpec(exchange.indicatorRef), + ) ) } @@ -129,10 +132,12 @@ class LcaMapper( ) } - fun technoInputExchange(psiExchange: LcaTechnoInputExchange): ETechnoExchange { - return ETechnoExchange( - dataExpression(psiExchange.dataExpression), - inputProductSpec(psiExchange.inputProductSpec), + fun technoInputExchange(psiExchange: LcaTechnoInputExchange): TechnoBlock { + return ETechnoBlockEntry( + ETechnoExchange( + dataExpression(psiExchange.dataExpression), + inputProductSpec(psiExchange.inputProductSpec), + ) ) } @@ -189,11 +194,13 @@ class LcaMapper( return dataExpression(element.dataExpression) } - private fun bioExchange(psiExchange: LcaBioExchange, symbolTable: SymbolTable): EBioExchange { + private fun bioExchange(psiExchange: LcaBioExchange, symbolTable: SymbolTable): BioBlock { val quantity = dataExpression(psiExchange.dataExpression) - return EBioExchange( - quantity, - substanceSpec(psiExchange.substanceSpec, quantity, symbolTable) + return EBioBlockEntry( + EBioExchange( + quantity, + substanceSpec(psiExchange.substanceSpec, quantity, symbolTable) + ) ) } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/testing/LcaTestRunner.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/testing/LcaTestRunner.kt index 506448cf8..36980155a 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/testing/LcaTestRunner.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/testing/LcaTestRunner.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.testing import ch.kleis.lcaac.core.assessment.ContributionAnalysisProgram +import ch.kleis.lcaac.core.datasource.CsvSourceOperations import ch.kleis.lcaac.core.lang.register.DataKey import ch.kleis.lcaac.core.lang.register.ProcessKey import ch.kleis.lcaac.core.lang.register.Register @@ -22,18 +23,22 @@ import ch.kleis.lcaac.plugin.psi.LcaRangeAssertion import ch.kleis.lcaac.plugin.psi.LcaTest import com.intellij.openapi.application.runReadAction import com.intellij.openapi.project.Project +import java.io.File class LcaTestRunner( private val project: Project, ) { - private val mapper = LcaMapper(BasicOperations) + private val ops = BasicOperations + private val mapper = LcaMapper(ops) + private val sourceOps = CsvSourceOperations(File(project.basePath!!), ops) + // TODO: Use testing objects from core package fun run(test: LcaTest): LcaTestResult { try { val symbolTable = runReadAction { val file = test.containingFile as LcaFile val collector = LcaFileCollector(project) - val parser = LcaLoader(collector.collect(file), BasicOperations) + val parser = LcaLoader(collector.collect(file), ops) parser.load() } val testCase = runReadAction { testCase(test) } @@ -42,7 +47,7 @@ class LcaTestRunner( processTemplates = Register(symbolTable.processTemplates) .plus(mapOf(ProcessKey(testCase.body.name) to testCase)) ) - val evaluator = Evaluator(updatedSymbolTable, BasicOperations) + val evaluator = Evaluator(updatedSymbolTable, ops, sourceOps) val trace = evaluator.trace(testCase) val program = ContributionAnalysisProgram(trace.getSystemValue(), trace.getEntryPoint()) val analysis = program.run() @@ -50,7 +55,7 @@ class LcaTestRunner( val target = trace.getEntryPoint().products.first().port() val results = assertions.map { assertion -> val ports = analysis.findAllPortsByShortName(assertion.ref) - val impact = with(QuantityValueOperations(BasicOperations)) { + val impact = with(QuantityValueOperations(ops)) { ports.map { if (analysis.isControllable(it)) analysis.getPortContribution(target, it) else analysis.supplyOf(it) @@ -80,15 +85,15 @@ class LcaTestRunner( test.variablesList.flatMap { it.assignmentList } .map { DataKey(it.getDataRef().name) to mapper.dataExpression(it.getValue()) } ) - val reducer = DataExpressionReducer(data, BasicOperations) + val reducer = DataExpressionReducer(data, symbolTable.dataSources, ops, sourceOps) return test.assertList.flatMap { it.rangeAssertionList } .map { val loExpression = mapper.dataExpression(it.lo()) val loReduced = reducer.reduce(loExpression) val hiExpression = mapper.dataExpression(it.hi()) val hiReduced = reducer.reduce(hiExpression) - val lo = with(ToValue(BasicOperations)) { loReduced.toValue() } - val hi = with(ToValue(BasicOperations)) { hiReduced.toValue() } + val lo = with(ToValue(ops)) { loReduced.toValue() } + val hi = with(ToValue(ops)) { hiReduced.toValue() } RangeAssertion(it.uid.name, lo, hi) } } From 256bf9219d90d2eaf32c9f3278334f97a745b5d2 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 21 Jan 2024 22:43:20 +0100 Subject: [PATCH 03/24] make tests compile --- .../plugin/actions/csv/CsvProcessorTest.kt | 7 +- .../sankey/SankeyGraphWindowBuilderTest.kt | 3 +- .../ch/kleis/lcaac/plugin/e2e/E2ETest.kt | 45 +++++++------ .../lcaac/plugin/fixture/ProcessFixture.kt | 16 +++-- .../SubstanceCharacterizationFixture.kt | 13 ++-- .../lcaac/plugin/fixture/TemplateFixture.kt | 17 +++-- .../plugin/language/loader/LcaLoaderTest.kt | 65 +++++++++++-------- .../ContributionAnalysisWindowTest.kt | 3 +- 8 files changed, 97 insertions(+), 72 deletions(-) diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt index cc838e575..5d1734f40 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt @@ -10,6 +10,7 @@ import ch.kleis.lcaac.plugin.language.loader.LcaLoader import ch.kleis.lcaac.plugin.language.psi.LcaFile import com.intellij.psi.PsiManager import com.intellij.testFramework.fixtures.BasePlatformTestCase +import io.mockk.mockk import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -46,7 +47,7 @@ class CsvProcessorTest : BasePlatformTestCase() { val file = PsiManager.getInstance(project).findFile(vf) as LcaFile val parser = LcaLoader(sequenceOf(file, UnitFixture.getInternalUnitFile(myFixture)), ops) val symbolTable = parser.load() - val processor = CsvProcessor(symbolTable) + val processor = CsvProcessor(mockk(), symbolTable) val cc = IndicatorValue( "cc", umap["kg"]!!, ) @@ -112,7 +113,7 @@ class CsvProcessorTest : BasePlatformTestCase() { val file = PsiManager.getInstance(project).findFile(vf) as LcaFile val parser = LcaLoader(sequenceOf(file, UnitFixture.getInternalUnitFile(myFixture)), ops) val symbolTable = parser.load() - val csvProcessor = CsvProcessor(symbolTable) + val csvProcessor = CsvProcessor(mockk(), symbolTable) val request = CsvRequest( "p", emptyMap(), @@ -177,7 +178,7 @@ class CsvProcessorTest : BasePlatformTestCase() { val file = PsiManager.getInstance(project).findFile(vf) as LcaFile val parser = LcaLoader(sequenceOf(file, UnitFixture.getInternalUnitFile(myFixture)), ops) val symbolTable = parser.load() - val csvProcessor = CsvProcessor(symbolTable) + val csvProcessor = CsvProcessor(mockk(), symbolTable) val request = CsvRequest( "p", mapOf("foo" to "bar"), diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/sankey/SankeyGraphWindowBuilderTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/sankey/SankeyGraphWindowBuilderTest.kt index 43f0b83b6..5764d9d52 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/sankey/SankeyGraphWindowBuilderTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/sankey/SankeyGraphWindowBuilderTest.kt @@ -14,6 +14,7 @@ import com.intellij.openapi.ui.naturalSorted import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.intellij.testFramework.fixtures.BasePlatformTestCase +import io.mockk.mockk import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -40,7 +41,7 @@ class SankeyGraphWindowBuilderTest : BasePlatformTestCase() { val parser = LcaLoader(sequenceOf(UnitFixture.getInternalUnitFile(myFixture), file), ops) val symbolTable = parser.load() val template = symbolTable.getTemplate(process)!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val assessment = ContributionAnalysisProgram(trace.getSystemValue(), trace.getEntryPoint()) val analysis = assessment.run() val sankeyPort = analysis.getControllablePorts().getElements().first() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt index 02122f9b3..3bbf0835e 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt @@ -10,6 +10,7 @@ import ch.kleis.lcaac.core.lang.evaluator.ToValue import ch.kleis.lcaac.core.lang.evaluator.reducer.DataExpressionReducer import ch.kleis.lcaac.core.lang.expression.EProcessTemplate import ch.kleis.lcaac.core.lang.expression.EQuantityScale +import ch.kleis.lcaac.core.lang.expression.ETechnoBlockEntry import ch.kleis.lcaac.core.lang.expression.EUnitLiteral import ch.kleis.lcaac.core.lang.value.FromProcessRefValue import ch.kleis.lcaac.core.lang.value.ProductValue @@ -27,6 +28,7 @@ import ch.kleis.lcaac.plugin.language.psi.LcaFile import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.intellij.testFramework.fixtures.BasePlatformTestCase +import io.mockk.mockk import junit.framework.TestCase import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -87,7 +89,7 @@ class E2ETest : BasePlatformTestCase() { // when val template = symbolTable.getTemplate("a_proc")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -181,7 +183,7 @@ class E2ETest : BasePlatformTestCase() { // when val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -254,7 +256,7 @@ class E2ETest : BasePlatformTestCase() { // when val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -306,7 +308,7 @@ class E2ETest : BasePlatformTestCase() { // when/then does not throw symbolTable.getTemplate("p") - ?.let { Evaluator(symbolTable, ops).trace(it) }!! + ?.let { Evaluator(symbolTable, ops, mockk()).trace(it) }!! } @Test @@ -340,7 +342,7 @@ class E2ETest : BasePlatformTestCase() { // when/then does not throw symbolTable.getTemplate("p") - ?.let { Evaluator(symbolTable, ops).trace(it) }!! + ?.let { Evaluator(symbolTable, ops, mockk()).trace(it) }!! } @Test @@ -368,7 +370,7 @@ class E2ETest : BasePlatformTestCase() { ) val kg = UnitValue(UnitSymbol.of("kg"), 1.0, Dimension.of("mass")) val symbolTable = createFilesAndSymbols(vf) - val csvProcessor = CsvProcessor(symbolTable) + val csvProcessor = CsvProcessor(mockk(), symbolTable) val request = CsvRequest( "p", emptyMap(), @@ -425,8 +427,9 @@ class E2ETest : BasePlatformTestCase() { """.trimIndent() ) val symbolTable = createFilesAndSymbols(vf) - val reducer = DataExpressionReducer(symbolTable.data, ops) - val expr = symbolTable.getTemplate("p")!!.body.inputs.first().quantity + val reducer = DataExpressionReducer(symbolTable.data, symbolTable.dataSources, ops, mockk()) + val block = symbolTable.getTemplate("p")!!.body.inputs.first() as ETechnoBlockEntry + val expr = block.entry.quantity // when val actual = reducer.reduce(expr) @@ -474,7 +477,7 @@ class E2ETest : BasePlatformTestCase() { val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -538,7 +541,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -594,7 +597,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("office")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -647,7 +650,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("office")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -706,7 +709,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("office")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -744,7 +747,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) val result = assessment.run().getImpactFactors() @@ -830,7 +833,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) @@ -871,7 +874,7 @@ class E2ETest : BasePlatformTestCase() { ) val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val evaluator = Evaluator(symbolTable, ops) + val evaluator = Evaluator(symbolTable, ops, mockk()) // when + then val e = assertFailsWith(EvaluatorException::class, null) { evaluator.trace(template) } @@ -905,7 +908,7 @@ class E2ETest : BasePlatformTestCase() { ) val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val evaluator = Evaluator(symbolTable, ops) + val evaluator = Evaluator(symbolTable, ops, mockk()) // when + then val e = assertFailsWith(EvaluatorException::class, null) { evaluator.trace(template) } @@ -939,7 +942,7 @@ class E2ETest : BasePlatformTestCase() { ) val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val evaluator = Evaluator(symbolTable, ops) + val evaluator = Evaluator(symbolTable, ops, mockk()) // when, then does not throw evaluator.trace(template) @@ -974,7 +977,7 @@ class E2ETest : BasePlatformTestCase() { val template = symbolTable.getTemplate("p")!! // when/then - Evaluator(symbolTable, ops).trace(template) + Evaluator(symbolTable, ops, mockk()).trace(template) } @Test @@ -998,7 +1001,7 @@ class E2ETest : BasePlatformTestCase() { // when val symbolTable = createFilesAndSymbols(vf) val template = symbolTable.getTemplate("p")!! - val trace = Evaluator(symbolTable, ops).trace(template) + val trace = Evaluator(symbolTable, ops, mockk()).trace(template) val system = trace.getSystemValue() val assessment = ContributionAnalysisProgram(system, trace.getEntryPoint()) @@ -1045,7 +1048,7 @@ class E2ETest : BasePlatformTestCase() { val e = assertFailsWith( EvaluatorException::class, ) { - Evaluator(symbolTable, ops).trace(template) + Evaluator(symbolTable, ops, mockk()).trace(template) } assertEquals("incompatible dimensions: length³ vs mass for product in", e.message) } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/ProcessFixture.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/ProcessFixture.kt index b732320ee..b38409294 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/ProcessFixture.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/ProcessFixture.kt @@ -1,8 +1,6 @@ package ch.kleis.lcaac.plugin.fixture -import ch.kleis.lcaac.core.lang.expression.EBioExchange -import ch.kleis.lcaac.core.lang.expression.EProcess -import ch.kleis.lcaac.core.lang.expression.ETechnoExchange +import ch.kleis.lcaac.core.lang.expression.* class ProcessFixture { companion object { @@ -13,13 +11,19 @@ class ProcessFixture { ETechnoExchange(QuantityFixture.oneKilogram, ProductFixture.carrot), ), inputs = listOf( - ETechnoExchange(QuantityFixture.oneLitre, ProductFixture.water), + ETechnoBlockEntry( + ETechnoExchange(QuantityFixture.oneLitre, ProductFixture.water), + ) ), biosphere = listOf( - EBioExchange(QuantityFixture.oneKilogram, SubstanceFixture.propanol), + EBioBlockEntry( + EBioExchange(QuantityFixture.oneKilogram, SubstanceFixture.propanol), + ) ), impacts = listOf( - ImpactFixture.oneClimateChange + EImpactBlockEntry( + ImpactFixture.oneClimateChange + ) ) ) } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/SubstanceCharacterizationFixture.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/SubstanceCharacterizationFixture.kt index 8601fd89e..9e04e0a4b 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/SubstanceCharacterizationFixture.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/SubstanceCharacterizationFixture.kt @@ -1,9 +1,6 @@ package ch.kleis.lcaac.plugin.fixture -import ch.kleis.lcaac.core.lang.expression.EBioExchange -import ch.kleis.lcaac.core.lang.expression.EImpact -import ch.kleis.lcaac.core.lang.expression.ESubstanceCharacterization -import ch.kleis.lcaac.core.lang.expression.ESubstanceSpec +import ch.kleis.lcaac.core.lang.expression.* import ch.kleis.lcaac.core.math.basic.BasicNumber class SubstanceCharacterizationFixture { @@ -11,7 +8,9 @@ class SubstanceCharacterizationFixture { val propanolCharacterization = ESubstanceCharacterization( referenceExchange = EBioExchange(QuantityFixture.oneKilogram, SubstanceFixture.propanol), impacts = listOf( - EImpact(QuantityFixture.oneKilogram, IndicatorFixture.climateChange), + EImpactBlockEntry( + EImpact(QuantityFixture.oneKilogram, IndicatorFixture.climateChange), + ) ), ) @@ -19,7 +18,9 @@ class SubstanceCharacterizationFixture { ESubstanceCharacterization( referenceExchange = EBioExchange(QuantityFixture.oneKilogram, substance), impacts = listOf( - EImpact(QuantityFixture.oneKilogram, IndicatorFixture.climateChange) + EImpactBlockEntry( + EImpact(QuantityFixture.oneKilogram, IndicatorFixture.climateChange) + ) ) ) } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/TemplateFixture.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/TemplateFixture.kt index f94b1382a..daa76df2a 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/TemplateFixture.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/fixture/TemplateFixture.kt @@ -1,9 +1,6 @@ package ch.kleis.lcaac.plugin.fixture -import ch.kleis.lcaac.core.lang.expression.EDataRef -import ch.kleis.lcaac.core.lang.expression.EProcess -import ch.kleis.lcaac.core.lang.expression.EProcessTemplate -import ch.kleis.lcaac.core.lang.expression.ETechnoExchange +import ch.kleis.lcaac.core.lang.expression.* class TemplateFixture { companion object { @@ -20,7 +17,9 @@ class TemplateFixture { ETechnoExchange(EDataRef("q_carrot"), ProductFixture.carrot), ), inputs = listOf( - ETechnoExchange(EDataRef("q_water"), ProductFixture.water), + ETechnoBlockEntry( + ETechnoExchange(EDataRef("q_water"), ProductFixture.water), + ) ), ) ) @@ -34,7 +33,9 @@ class TemplateFixture { ETechnoExchange(QuantityFixture.twoKilograms, ProductFixture.carrot), ), inputs = listOf( - ETechnoExchange(QuantityFixture.oneGram, ProductFixture.carrot), + ETechnoBlockEntry( + ETechnoExchange(QuantityFixture.oneGram, ProductFixture.carrot), + ) ), ) ) @@ -45,7 +46,9 @@ class TemplateFixture { ETechnoExchange(EDataRef("q_carrot"), ProductFixture.carrot), ), inputs = listOf( - ETechnoExchange(EDataRef("q_water"), ProductFixture.water), + ETechnoBlockEntry( + ETechnoExchange(EDataRef("q_water"), ProductFixture.water), + ) ), ) ) diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt index 006f16249..7d38532c5 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt @@ -6,9 +6,9 @@ import arrow.optics.typeclasses.Index import ch.kleis.lcaac.core.lang.SymbolTable import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException import ch.kleis.lcaac.core.lang.expression.* +import ch.kleis.lcaac.core.lang.expression.optics.everyEntry import ch.kleis.lcaac.core.math.basic.BasicNumber import ch.kleis.lcaac.core.math.basic.BasicOperations -import ch.kleis.lcaac.core.prelude.Prelude import ch.kleis.lcaac.plugin.fixture.UnitFixture import ch.kleis.lcaac.plugin.language.psi.LcaFile import com.intellij.testFramework.ParsingTestCase @@ -214,7 +214,8 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { val template = symbolTable.getTemplate("a") as ProcessTemplateExpression val actual = (ProcessTemplateExpression.eProcessTemplate().body().biosphere() compose - Every.list() compose EBioExchange.substance()).firstOrNull(template) + Every.list() compose BlockExpression.everyEntry() compose + EBioExchange.substance()).firstOrNull(template) // then assertEquals("lu", actual?.name) @@ -517,10 +518,12 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { ), ), inputs = listOf( - ETechnoExchange( - EQuantityScale(ops.pure(10.0), EDataRef("l")), - EProductSpec("water"), - ), + ETechnoBlockEntry( + ETechnoExchange( + EQuantityScale(ops.pure(10.0), EDataRef("l")), + EProductSpec("water"), + ), + ) ), ) ) @@ -628,9 +631,10 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { val symbolTable = parser.load() val template = symbolTable.getTemplate("a")!! val actual = ( - ProcessTemplateExpression.eProcessTemplate().body().inputs().index(Index.list(), 0) compose - ETechnoExchange.quantity() - ).getOrNull(template)!! + ProcessTemplateExpression.eProcessTemplate().body().inputs().index(Index.list(), 0) compose + BlockExpression.everyEntry() compose + ETechnoExchange.quantity() + ).getAll(template).first() // then val expected = EQuantityDiv( @@ -661,9 +665,10 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { val symbolTable = parser.load() val template = symbolTable.getTemplate("a")!! val actual = ( - ProcessTemplateExpression.eProcessTemplate().body().inputs().index(Index.list(), 0) compose - ETechnoExchange.quantity() - ).getOrNull(template)!! + ProcessTemplateExpression.eProcessTemplate().body().inputs().index(Index.list(), 0) compose + BlockExpression.everyEntry() compose + ETechnoExchange.quantity() + ).getAll(template).first() // then val expected = EQuantityMul( @@ -701,17 +706,19 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { // then val expected = listOf( - ETechnoExchange( - EQuantityScale(ops.pure(10.0), EDataRef("l")), - EProductSpec( - "water", - fromProcess = FromProcess( - "water_proc", - MatchLabels(emptyMap()), - mapOf("x" to EQuantityScale(ops.pure(3.0), EDataRef("l"))), - ), - ) - ), + ETechnoBlockEntry( + ETechnoExchange( + EQuantityScale(ops.pure(10.0), EDataRef("l")), + EProductSpec( + "water", + fromProcess = FromProcess( + "water_proc", + MatchLabels(emptyMap()), + mapOf("x" to EQuantityScale(ops.pure(3.0), EDataRef("l"))), + ), + ) + ), + ) ) assertEquals(expected, actual) } @@ -765,9 +772,11 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { ), ), impacts = listOf( - EImpact( - EQuantityScale(ops.pure(1.0), EDataRef("kg")), - EIndicatorSpec("climate_change"), + EImpactBlockEntry( + EImpact( + EQuantityScale(ops.pure(1.0), EDataRef("kg")), + EIndicatorSpec("climate_change"), + ) ) ) ) @@ -1016,7 +1025,9 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { val template = symbolTable.getTemplate("a") as ProcessTemplateExpression val actual = (ProcessTemplateExpression.eProcessTemplate().body().impacts() compose - Every.list() compose EImpact.indicator()).firstOrNull(template) + Every.list() compose + BlockExpression.everyEntry() compose + EImpact.indicator()).firstOrNull(template) // then assertEquals("cc", actual?.name) diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/ui/toolwindow/ContributionAnalysisWindowTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/ui/toolwindow/ContributionAnalysisWindowTest.kt index c8195adf5..f179d2979 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/ui/toolwindow/ContributionAnalysisWindowTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/ui/toolwindow/ContributionAnalysisWindowTest.kt @@ -19,6 +19,7 @@ import com.intellij.testFramework.fixtures.BasePlatformTestCase import com.intellij.ui.components.JBScrollPane import com.intellij.ui.components.JBViewport import com.intellij.ui.table.JBTable +import io.mockk.mockk import org.jdesktop.swingx.plaf.basic.core.BasicTransferable import org.junit.Test import org.junit.runner.RunWith @@ -240,7 +241,7 @@ class ContributionAnalysisWindowTest : BasePlatformTestCase() { val loader = LcaLoader(sequenceOf(lcaFile, builtinUnitsLcaFile), ops) val symbolTable = loader.load() val template = symbolTable.getTemplate("p")!! - val evaluator = Evaluator(symbolTable, ops) + val evaluator = Evaluator(symbolTable, ops, mockk()) val trace = evaluator.trace(template) val program = ContributionAnalysisProgram(trace.getSystemValue(), trace.getEntryPoint()) return program.run() From f83d6f0597f76095aaf7e8649cccaf9f218ba43b Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 21 Jan 2024 23:20:32 +0100 Subject: [PATCH 04/24] bnf: added datasources, col ops, for_each blocks --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 42 ++++++++++++++++--- .../ch/kleis/lcaac/plugin/language/Lca.flex | 7 +++- .../ide/insight/LcaBioExchangeAnnotator.kt | 8 ++-- .../LcaTechnoInputExchangeAnnotator.kt | 4 +- .../lcaac/plugin/language/loader/LcaMapper.kt | 38 ++++++++++------- .../type_checker/PsiLcaTypeChecker.kt | 16 +++---- 6 files changed, 76 insertions(+), 39 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index e04c2e584..3bb28d8d4 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -51,6 +51,13 @@ BETWEEN_KEYWORD = 'between' AND_KEYWORD = 'and' + DATASOURCE_KEYWORD = 'datasource' + LOCATION_KEYWORD = 'location' + SCHEMA_KEYWORD = 'schema' + FOR_EACH_KEYWORD = 'for_each' + IN_KEYWORD = 'in' + SUM_KEYWORD = 'sum' + NUMBER = 'number' LSQBRACE = ']' RSQBRACE = '[' @@ -80,7 +87,7 @@ LCA File */ -lcaFile ::= package? import* (process | test | unitDefinition | substance | globalVariables )* +lcaFile ::= package? import* (process | test | dataSourceDefinition | unitDefinition | substance | globalVariables )* /* Package @@ -96,6 +103,15 @@ import ::= "import" urn { mixin="ch.kleis.lcaac.plugin.language.psi.mixin.trait.PsiUrnOwnerMixin" } +/* + Data source + */ + +dataSourceDefinition ::= 'datasource' dataSourceRef '{' (locationField | schemaDefinition)* '}' +locationField ::= 'location' '=' STRING_LITERAL +schemaDefinition ::= 'schema' '{' columnDefinition* '}' +columnDefinition ::= STRING_LITERAL '=' dataExpression + /* Global variables */ @@ -220,7 +236,7 @@ params ::= "params" "{" assignment* "}" variables ::= "variables" "{" assignment* "}" -assignment ::= dataRef "=" dataExpression { +assignment ::= dataRef (('=' dataExpression) | ('from' dataSourceRef)){ implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiAssignment"] mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiAssignmentMixin" } @@ -245,10 +261,16 @@ block_impacts ::= "impacts" "{" impactExchange* "}" Exchanges */ -technoInputExchange ::= dataExpression inputProductSpec technoProductExchange ::= dataExpression outputProductSpec -bioExchange ::= dataExpression substanceSpec -impactExchange ::= dataExpression indicatorRef +technoInputExchange ::= terminalTechnoInputExchange + | 'for_each' dataRef 'in' dataSourceRef '{' (variables | technoInputExchange)* '}' +terminalTechnoInputExchange ::= dataExpression inputProductSpec +bioExchange ::= terminalBioExchange + | 'for_each' dataRef 'in' dataSourceRef '{' (variables | bioExchange)* '}' +terminalBioExchange ::= dataExpression substanceSpec +impactExchange ::= terminalImpactExchange + | 'for_each' dataRef 'in' dataSourceRef '{' (variables | impactExchange)* '}' +terminalImpactExchange ::= dataExpression indicatorRef /* Quantity @@ -259,10 +281,12 @@ dataExpression ::= addGroup | mulGroup | exponentialQuantityExpression | baseGroup + | colGroup private addGroup ::= addQuantityExpression | subQuantityExpression private mulGroup ::= scaleQuantityExpression | mulQuantityExpression | divQuantityExpression -private baseGroup ::= parenQuantityExpression | stringExpression | dataRef +private baseGroup ::= parenQuantityExpression | stringExpression | sliceExpression +private colGroup ::= colExpression fake binaryOperatorExpression ::= dataExpression dataExpression { extends=dataExpression @@ -280,6 +304,9 @@ exponentialQuantityExpression ::= dataExpression "^" NUMBER { extends=dataExpres parenQuantityExpression ::= "(" dataExpression ")" { extends=dataExpression } scaleQuantityExpression ::= NUMBER dataExpression { extends=dataExpression methods=[scale="NUMBER"]} stringExpression ::= STRING_LITERAL { extends=dataExpression } +sliceExpression ::= dataRef ('[' columnRef ']')? { extends=dataExpression } +columnRef ::= STRING_LITERAL +colExpression ::= 'sum' '(' dataSourceRef ',' columnRef ('*' columnRef)* ')' { extends=dataExpression } /* @@ -336,6 +363,9 @@ testRef ::= uid { implements=["ch.kleis.lcaac.plugin.language.psi.type.trait.PsiUIDOwner"] mixin="ch.kleis.lcaac.plugin.language.psi.mixin.ref.PsiTestRefMixin" } + +dataSourceRef ::= uid + /* Spec */ diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex index b2b64b225..f80b06627 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex @@ -98,7 +98,12 @@ CommentContent = .* "between" { return LcaTypes.BETWEEN_KEYWORD; } "and" { return LcaTypes.AND_KEYWORD; } - + "datasource" { return LcaTypes.DATASOURCE_KEYWORD; } + "location" { return LcaTypes.LOCATION_KEYWORD; } + "schema" { return LcaTypes.SCHEMA_KEYWORD; } + "for_each" { return LcaTypes.FOR_EACH_KEYWORD; } + "in" { return LcaTypes.IN_KEYWORD; } + "sum" { return LcaTypes.SUM_KEYWORD; } [-]?{Number_Int} ("." {Number_Int}? )? {Number_Exp}? { return LcaTypes.NUMBER; } {Identifier} { return LcaTypes.IDENTIFIER; } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotator.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotator.kt index 3146df019..ae74522ae 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotator.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotator.kt @@ -5,15 +5,15 @@ import ch.kleis.lcaac.plugin.language.ide.insight.AnnotatorHelper.annotateWarnWi import ch.kleis.lcaac.plugin.language.psi.type.PsiSubstance import ch.kleis.lcaac.plugin.language.type_checker.PsiLcaTypeChecker import ch.kleis.lcaac.plugin.language.type_checker.PsiTypeCheckException -import ch.kleis.lcaac.plugin.psi.LcaBioExchange import ch.kleis.lcaac.plugin.psi.LcaSubstanceSpec +import ch.kleis.lcaac.plugin.psi.LcaTerminalBioExchange import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.Annotator import com.intellij.psi.PsiElement class LcaBioExchangeAnnotator : Annotator { override fun annotate(element: PsiElement, holder: AnnotationHolder) { - if (element !is LcaBioExchange) { + if (element !is LcaTerminalBioExchange) { return } @@ -21,7 +21,7 @@ class LcaBioExchangeAnnotator : Annotator { checkType(element, holder) } - private fun checkReferenceResolution(element: LcaBioExchange, holder: AnnotationHolder) { + private fun checkReferenceResolution(element: LcaTerminalBioExchange, holder: AnnotationHolder) { val target = element.substanceSpec.reference?.resolve() if (target == null || target !is PsiSubstance) { val spec = element.substanceSpec @@ -29,7 +29,7 @@ class LcaBioExchangeAnnotator : Annotator { } } - private fun checkType(element: LcaBioExchange, holder: AnnotationHolder) { + private fun checkType(element: LcaTerminalBioExchange, holder: AnnotationHolder) { val checker = PsiLcaTypeChecker() try { checker.check(element) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt index f9c19dc9d..e5ed24705 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt @@ -8,14 +8,14 @@ import ch.kleis.lcaac.plugin.language.type_checker.PsiLcaTypeChecker import ch.kleis.lcaac.plugin.language.type_checker.PsiTypeCheckException import ch.kleis.lcaac.plugin.psi.LcaInputProductSpec import ch.kleis.lcaac.plugin.psi.LcaOutputProductSpec -import ch.kleis.lcaac.plugin.psi.LcaTechnoInputExchange +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.Annotator import com.intellij.psi.PsiElement class LcaTechnoInputExchangeAnnotator : Annotator { override fun annotate(element: PsiElement, holder: AnnotationHolder) { - if (element !is LcaTechnoInputExchange) { + if (element !is LcaTerminalTechnoInputExchange) { return } val targets = diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt index 3def4e099..7b499e946 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt @@ -118,12 +118,14 @@ class LcaMapper( private fun impact(exchange: LcaImpactExchange): ImpactBlock { - return EImpactBlockEntry( - EImpact( - dataExpression(exchange.dataExpression), - indicatorSpec(exchange.indicatorRef), + return exchange.terminalImpactExchange?.let { + EImpactBlockEntry( + EImpact( + dataExpression(it.dataExpression), + indicatorSpec(it.indicatorRef), + ) ) - ) + } ?: EImpactBlockForEach("", "", emptyMap(), emptyList()) } private fun indicatorSpec(variable: PsiIndicatorRef): EIndicatorSpec { @@ -133,12 +135,14 @@ class LcaMapper( } fun technoInputExchange(psiExchange: LcaTechnoInputExchange): TechnoBlock { - return ETechnoBlockEntry( - ETechnoExchange( - dataExpression(psiExchange.dataExpression), - inputProductSpec(psiExchange.inputProductSpec), + return psiExchange.terminalTechnoInputExchange?.let { + ETechnoBlockEntry( + ETechnoExchange( + dataExpression(it.dataExpression), + inputProductSpec(it.inputProductSpec), + ) ) - ) + } ?: ETechnoBlockForEach("", "", emptyMap(), emptyList()) } private fun outputProductSpec( @@ -195,13 +199,15 @@ class LcaMapper( } private fun bioExchange(psiExchange: LcaBioExchange, symbolTable: SymbolTable): BioBlock { - val quantity = dataExpression(psiExchange.dataExpression) - return EBioBlockEntry( - EBioExchange( - quantity, - substanceSpec(psiExchange.substanceSpec, quantity, symbolTable) + return psiExchange.terminalBioExchange?.let { + val quantity = dataExpression(it.dataExpression) + EBioBlockEntry( + EBioExchange( + quantity, + substanceSpec(it.substanceSpec, quantity, symbolTable) + ) ) - ) + } ?: EBioBlockForEach("", "", emptyMap(), emptyList()) } fun dataExpression(dataExpression: LcaDataExpression): DataExpression { diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt index 3c209fde7..70c37caa5 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt @@ -2,12 +2,8 @@ package ch.kleis.lcaac.plugin.language.type_checker import ch.kleis.lcaac.core.lang.dimension.Dimension import ch.kleis.lcaac.core.lang.type.* -import ch.kleis.lcaac.plugin.language.psi.type.PsiAssignment -import ch.kleis.lcaac.plugin.language.psi.type.PsiGlobalAssignment import ch.kleis.lcaac.plugin.language.psi.type.PsiProcess -import ch.kleis.lcaac.plugin.language.psi.type.PsiSubstance import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataRef -import ch.kleis.lcaac.plugin.language.psi.type.unit.PsiUnitDefinition import ch.kleis.lcaac.plugin.language.psi.type.unit.UnitDefinitionType import ch.kleis.lcaac.plugin.psi.* import com.intellij.psi.PsiElement @@ -22,15 +18,15 @@ class PsiLcaTypeChecker { is LcaGlobalAssignment -> checkDataExpression(element.getValue()) is LcaAssignment -> checkDataExpression(element.getValue()) is LcaLabelAssignment -> TString - is LcaTechnoInputExchange -> checkTechnoInputExchange(element) + is LcaTerminalTechnoInputExchange -> checkTerminalTechnoInputExchange(element) is LcaTechnoProductExchange -> checkTechnoProductExchange(element) - is LcaBioExchange -> checkBioExchange(element) + is LcaTerminalBioExchange -> checkTerminalBioExchange(element) else -> throw PsiTypeCheckException("Uncheckable type: $element") } } - private fun checkBioExchange(lcaBioExchange: LcaBioExchange): TBioExchange { - return rec.guard { el: LcaBioExchange -> + private fun checkTerminalBioExchange(lcaBioExchange: LcaTerminalBioExchange): TBioExchange { + return rec.guard { el: LcaTerminalBioExchange -> val tyQuantity = checkDataExpression(el.dataExpression, TQuantity::class.java) val name = el.substanceSpec.name val comp = el.substanceSpec.getCompartmentField()?.getValue() ?: "" @@ -58,8 +54,8 @@ class PsiLcaTypeChecker { }(element) } - private fun checkTechnoInputExchange(element: LcaTechnoInputExchange): TTechnoExchange { - return rec.guard { el: LcaTechnoInputExchange -> + private fun checkTerminalTechnoInputExchange(element: LcaTerminalTechnoInputExchange): TTechnoExchange { + return rec.guard { el: LcaTerminalTechnoInputExchange -> val tyQuantity = checkDataExpression(el.dataExpression, TQuantity::class.java) val productName = el.inputProductSpec.name el.inputProductSpec.reference?.resolve()?.let { From 6fdbe32b6bf2de5674c214bb2631d569f4d57238 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 21 Jan 2024 23:25:11 +0100 Subject: [PATCH 05/24] syntax higlight --- .../plugin/language/ide/syntax/LcaSyntaxHighlighter.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt index a6a52907a..209687bfc 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt @@ -45,7 +45,8 @@ class LcaSyntaxHighlighter : SyntaxHighlighterBase() { VARIABLES_KEYWORD, LAND_USE_KEYWORD, PRODUCTS_KEYWORD, INPUTS_KEYWORD, EMISSIONS_KEYWORD, RESOURCES_KEYWORD, - TEST_KEYWORD, GIVEN_KEYWORD, ASSERT_KEYWORD, BETWEEN_KEYWORD, AND_KEYWORD -> KEYWORD_KEYS + TEST_KEYWORD, GIVEN_KEYWORD, ASSERT_KEYWORD, BETWEEN_KEYWORD, AND_KEYWORD, + DATASOURCE_KEYWORD, SCHEMA_KEYWORD, FOR_EACH_KEYWORD, IN_KEYWORD -> KEYWORD_KEYS IDENTIFIER -> IDENTIFIER_KEYS @@ -54,7 +55,8 @@ class LcaSyntaxHighlighter : SyntaxHighlighterBase() { DIMENSION_KEYWORD, ALIAS_FOR_KEYWORD, REFERENCE_UNIT_KEYWORD, SYMBOL_KEYWORD, NAME_KEYWORD, - TYPE_KEYWORD, COMPARTMENT_KEYWORD, SUB_COMPARTMENT_KEYWORD -> FIELD_KEYS + TYPE_KEYWORD, COMPARTMENT_KEYWORD, SUB_COMPARTMENT_KEYWORD, + LOCATION_KEYWORD, SUM_KEYWORD -> FIELD_KEYS TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS From 3d5abacd5ee3effa4023df32f3482375a607268b Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 21 Jan 2024 23:37:37 +0100 Subject: [PATCH 06/24] make tests compile --- .../insight/LcaBioExchangeAnnotatorTest.kt | 5 ++- .../LcaTechnoInputExchangeAnnotatorTest.kt | 5 ++- .../loader/DefaultRefFileResolverTest.kt | 7 ++-- .../DataRefCollectorScopeProcessorTest.kt | 4 +- ...taRefExactNameMatcherScopeProcessorTest.kt | 4 +- .../psi/reference/DataReferenceTest.kt | 6 ++- .../psi/reference/LabelReferenceTest.kt | 7 ++-- .../psi/reference/ParameterReferenceTest.kt | 7 +++- .../ProcessReferenceFromPsiProcessRefTest.kt | 11 +++-- ...ReferenceFromPsiProcessTemplateSpecTest.kt | 11 +++-- ...bstanceReferenceFromPsiSubstanceRefTest.kt | 6 ++- ...stanceReferenceFromPsiSubstanceSpecTest.kt | 21 ++++++---- .../LcaMatchLabelsEvaluatorTest.kt | 41 +++++++++++-------- .../type_checker/PsiLcaTypeCheckerTest.kt | 7 ++-- 14 files changed, 90 insertions(+), 52 deletions(-) diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt index 45f46c3a6..eafc15ed3 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt @@ -1,6 +1,9 @@ package ch.kleis.lcaac.plugin.language.ide.insight +import ch.kleis.lcaac.core.lang.expression.EBioBlockEntry +import ch.kleis.lcaac.core.math.basic.BasicNumber import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalBioExchange import com.intellij.codeInspection.ProblemHighlightType import com.intellij.lang.annotation.HighlightSeverity import com.intellij.testFramework.fixtures.BasePlatformTestCase @@ -33,7 +36,7 @@ class LcaBioExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() + .getEmissions().first() as LcaTerminalBioExchange val mock = AnnotationHolderMock() val annotator = LcaBioExchangeAnnotator() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt index 5a418d70e..295290657 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.ide.insight import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInspection.ProblemHighlightType import com.intellij.lang.annotation.HighlightSeverity import com.intellij.testFramework.fixtures.BasePlatformTestCase @@ -33,7 +34,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() @@ -76,7 +77,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt index 5d1749007..760246824 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt @@ -1,7 +1,7 @@ package ch.kleis.lcaac.plugin.language.loader -import ch.kleis.lcaac.plugin.language.loader.DefaultRefFileResolver import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.openapi.ui.naturalSorted import com.intellij.testFramework.fixtures.BasePlatformTestCase import org.junit.Test @@ -32,8 +32,9 @@ class DefaultRefFileResolverTest : BasePlatformTestCase() { } """.trimIndent() ) - val target = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val target = element .inputProductSpec .getProcessTemplateSpec()!! myFixture.createFile( diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt index e43f6211b..45132cdd7 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt @@ -2,6 +2,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex import ch.kleis.lcaac.plugin.psi.LcaDataRef +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.openapi.ui.naturalSorted import com.intellij.testFramework.fixtures.BasePlatformTestCase @@ -56,7 +57,8 @@ class DataRefCollectorScopeProcessorTest : BasePlatformTestCase() { """.trimIndent() ) val process = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p", mapOf("d" to "LABEL")).first() - val target = process.getInputs().first() + val element = process.getInputs().first() as LcaTerminalTechnoInputExchange + val target = element .dataExpression as LcaDataRef // when diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt index c5d0e305a..586d3d09e 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt @@ -3,6 +3,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.loader.LcaParserDefinition import ch.kleis.lcaac.plugin.language.psi.LcaFile import ch.kleis.lcaac.plugin.psi.LcaDataRef +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.testFramework.ParsingTestCase import junit.framework.TestCase import org.junit.Test @@ -64,7 +65,8 @@ class DataRefExactNameMatcherScopeProcessorTest : ParsingTestCase("", "lca", Lca ) as LcaFile val process = file.getProcesses().first() val assignment = process.getLabelsList().first().labelAssignmentList.first() - val dataRef = process.getInputs().first() + val element = process.getInputs().first() as LcaTerminalTechnoInputExchange + val dataRef = element .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt index 249a92700..6a8ecf37d 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt @@ -6,6 +6,7 @@ import ch.kleis.lcaac.plugin.language.psi.stub.substance.SubstanceKeyIndex import ch.kleis.lcaac.plugin.language.psi.stub.unit.UnitStubKeyIndex import ch.kleis.lcaac.plugin.psi.LcaDataRef import ch.kleis.lcaac.plugin.psi.LcaScaleQuantityExpression +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.testFramework.fixtures.BasePlatformTestCase import junit.framework.TestCase @@ -68,8 +69,9 @@ class DataReferenceTest : BasePlatformTestCase() { val pkgName = "language.psi.reference.quantity.test_resolve_whenFromProcessParameter" val fqn = "$pkgName.caller" val process = ProcessStubKeyIndex.findProcesses(project, fqn).first() - val ref = process - .getInputs().first() + val element = process + .getInputs().first() as LcaTerminalTechnoInputExchange + val ref = element .inputProductSpec .getProcessTemplateSpec()!! .argumentList.first() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt index fce0aea70..550dcc6ee 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.testFramework.fixtures.BasePlatformTestCase import org.junit.Test import org.junit.runner.RunWith @@ -65,10 +66,10 @@ class LabelReferenceTest : BasePlatformTestCase() { } """.trimIndent() ) - val ref = ProcessStubKeyIndex.findProcesses( + val element = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p", - ).first().getInputs() - .first() + ).first().getInputs().first() as LcaTerminalTechnoInputExchange + val ref = element .inputProductSpec.getProcessTemplateSpec()!! .getMatchLabels()!!.labelSelectorList.first() .labelRef diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt index 783dc2f8c..cf8036b31 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.testFramework.fixtures.BasePlatformTestCase import junit.framework.TestCase @@ -48,7 +49,8 @@ class ParameterReferenceTest : BasePlatformTestCase() { ) val fqn = "$pkgName.p" val process = ProcessStubKeyIndex.findProcesses(project, fqn).first() - val ref = process.getInputs().first() + val element = process.getInputs().first() as LcaTerminalTechnoInputExchange + val ref = element .inputProductSpec .getProcessTemplateSpec()!! .argumentList.first() @@ -96,7 +98,8 @@ class ParameterReferenceTest : BasePlatformTestCase() { ) val fqn = "$pkgName.p" val process = ProcessStubKeyIndex.findProcesses(project, fqn).first() - val ref = process.getInputs().first() + val first = process.getInputs().first() as LcaTerminalTechnoInputExchange + val ref = first .inputProductSpec .getProcessTemplateSpec()!! .argumentList.first() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt index 8b87efac0..029bf544b 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.testFramework.fixtures.BasePlatformTestCase import junit.framework.TestCase @@ -58,8 +59,9 @@ class ProcessReferenceFromPsiProcessRefTest : BasePlatformTestCase() { } """.trimIndent() ) - val ref = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val ref = element .inputProductSpec .getProcessTemplateSpec()!! .getProcessRef() @@ -135,8 +137,9 @@ class ProcessReferenceFromPsiProcessRefTest : BasePlatformTestCase() { } """.trimIndent() ) - val ref = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val ref = first .inputProductSpec .getProcessTemplateSpec()!! .getProcessRef() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt index 4361a2b19..4cd146420 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.testFramework.fixtures.BasePlatformTestCase import junit.framework.TestCase @@ -57,8 +58,9 @@ class ProcessReferenceFromPsiProcessTemplateSpecTest : BasePlatformTestCase() { } """.trimIndent() ) - val ref = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val ref = element .inputProductSpec .getProcessTemplateSpec()!! @@ -134,8 +136,9 @@ class ProcessReferenceFromPsiProcessTemplateSpecTest : BasePlatformTestCase() { } """.trimIndent() ) - val ref = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val ref = first .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt index cb1783380..5a4518764 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt @@ -3,6 +3,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.core.lang.expression.SubstanceType import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex import ch.kleis.lcaac.plugin.language.psi.stub.substance.SubstanceKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalBioExchange import com.intellij.testFramework.fixtures.BasePlatformTestCase import org.junit.Test import org.junit.runner.RunWith @@ -64,8 +65,9 @@ class SubstanceReferenceFromPsiSubstanceRefTest : BasePlatformTestCase() { } """.trimIndent() ) - val ref = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getEmissions().first() as LcaTerminalBioExchange + val ref = element .substanceSpec .getSubstanceRef() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt index 9b08a1d09..5948455b3 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt @@ -2,6 +2,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex import ch.kleis.lcaac.plugin.language.psi.stub.substance.SubstanceKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalBioExchange import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.testFramework.fixtures.BasePlatformTestCase import junit.framework.TestCase @@ -57,8 +58,9 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { } """.trimIndent() ) - val substanceSpec = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getEmissions().first() as LcaTerminalBioExchange + val substanceSpec = element .getSubstanceSpec() // when @@ -114,8 +116,9 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { } """.trimIndent() ) - val substanceSpec = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getResources().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getResources().first() as LcaTerminalBioExchange + val substanceSpec = element .getSubstanceSpec() // when @@ -165,8 +168,9 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { } """.trimIndent() ) - val substanceSpec = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getEmissions().first() as LcaTerminalBioExchange + val substanceSpec = element .getSubstanceSpec() // when @@ -222,8 +226,9 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { } """.trimIndent() ) - val spec = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getEmissions().first() as LcaTerminalBioExchange + val spec = element .getSubstanceSpec() // when diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt index 042e1e4cd..9ff354f08 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.type_checker import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.testFramework.fixtures.BasePlatformTestCase import org.junit.Test import kotlin.test.assertFailsWith @@ -25,8 +26,9 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = element .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -58,8 +60,9 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -91,8 +94,9 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -124,12 +128,13 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses( + val first = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p", mapOf("country" to "FR") ).first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -162,11 +167,12 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses( + val first = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p" ).first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -201,11 +207,12 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses( + val first = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p" ).first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -235,11 +242,12 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses( + val first = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p" ).first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! @@ -265,11 +273,12 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { } """.trimIndent() ) - val labels = ProcessStubKeyIndex.findProcesses( + val first = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p" ).first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val labels = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt index c26b659d9..85985507b 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt @@ -2,11 +2,11 @@ package ch.kleis.lcaac.plugin.language.type_checker import ch.kleis.lcaac.core.lang.dimension.Dimension import ch.kleis.lcaac.core.lang.type.* -import ch.kleis.lcaac.core.prelude.Prelude import ch.kleis.lcaac.plugin.fixture.DimensionFixture import ch.kleis.lcaac.plugin.language.psi.stub.global_assignment.GlobalAssigmentStubKeyIndex import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex import ch.kleis.lcaac.plugin.language.psi.stub.unit.UnitStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.testFramework.fixtures.BasePlatformTestCase import junit.framework.TestCase import org.junit.Test @@ -93,9 +93,10 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { } """.trimIndent() ) - val target = ProcessStubKeyIndex + val first = ProcessStubKeyIndex .findProcesses(project, "$pkgName.p", mapOf("geo" to "FR")).first() - .getInputs().first() + .getInputs().first() as LcaTerminalTechnoInputExchange + val target = first .inputProductSpec .getProcessTemplateSpec()!! .getMatchLabels()!! From fb1cf72a736e68b4b5c90e8096a58b2dc01a7112 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Mon, 22 Jan 2024 00:51:16 +0100 Subject: [PATCH 07/24] bnf: fix square brackets and some tests --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 10 ++++------ .../lcaac/plugin/actions/csv/CsvProcessorTest.kt | 8 ++++---- .../kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt | 14 +++++++------- .../ide/insight/LcaBioExchangeAnnotatorTest.kt | 2 +- .../LcaTechnoInputExchangeAnnotatorTest.kt | 10 +++++----- .../loader/DefaultRefFileResolverTest.kt | 2 +- .../DataRefCollectorScopeProcessorTest.kt | 2 +- .../DataRefExactNameMatcherScopeProcessorTest.kt | 2 +- .../language/psi/reference/DataReferenceTest.kt | 2 +- .../language/psi/reference/LabelReferenceTest.kt | 2 +- .../psi/reference/ParameterReferenceTest.kt | 4 ++-- .../ProcessReferenceFromPsiProcessRefTest.kt | 4 ++-- ...essReferenceFromPsiProcessTemplateSpecTest.kt | 4 ++-- .../SubstanceReferenceFromPsiSubstanceRefTest.kt | 2 +- ...SubstanceReferenceFromPsiSubstanceSpecTest.kt | 8 ++++---- .../type_checker/LcaMatchLabelsEvaluatorTest.kt | 16 ++++++++-------- .../type_checker/PsiLcaTypeCheckerTest.kt | 12 ++++++------ 17 files changed, 51 insertions(+), 53 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index 3bb28d8d4..4e8f05f4a 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -59,8 +59,8 @@ SUM_KEYWORD = 'sum' NUMBER = 'number' - LSQBRACE = ']' - RSQBRACE = '[' + LSQBRACE = '[' + RSQBRACE = ']' LPAREN = '(' RPAREN = ')' LBRACE = '{' @@ -281,12 +281,10 @@ dataExpression ::= addGroup | mulGroup | exponentialQuantityExpression | baseGroup - | colGroup private addGroup ::= addQuantityExpression | subQuantityExpression private mulGroup ::= scaleQuantityExpression | mulQuantityExpression | divQuantityExpression -private baseGroup ::= parenQuantityExpression | stringExpression | sliceExpression -private colGroup ::= colExpression +private baseGroup ::= parenQuantityExpression | stringExpression | colExpression | sliceExpression | dataRef fake binaryOperatorExpression ::= dataExpression dataExpression { extends=dataExpression @@ -304,8 +302,8 @@ exponentialQuantityExpression ::= dataExpression "^" NUMBER { extends=dataExpres parenQuantityExpression ::= "(" dataExpression ")" { extends=dataExpression } scaleQuantityExpression ::= NUMBER dataExpression { extends=dataExpression methods=[scale="NUMBER"]} stringExpression ::= STRING_LITERAL { extends=dataExpression } -sliceExpression ::= dataRef ('[' columnRef ']')? { extends=dataExpression } columnRef ::= STRING_LITERAL +sliceExpression ::= dataRef '[' columnRef ']' { extends=dataExpression } colExpression ::= 'sum' '(' dataSourceRef ',' columnRef ('*' columnRef)* ')' { extends=dataExpression } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt index 5d1734f40..3c2ab058f 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/actions/csv/CsvProcessorTest.kt @@ -104,7 +104,7 @@ class CsvProcessorTest : BasePlatformTestCase() { 1 kg out } inputs { - a + b + c in + a + b + c in_prod } } """.trimIndent() @@ -141,7 +141,7 @@ class CsvProcessorTest : BasePlatformTestCase() { out, actual.output ) val key = ProductValue( - "in", kg, + "in_prod", kg, ) assertEquals( QuantityValue(ops.pure(3.0), kg), actual.impacts[key] @@ -169,7 +169,7 @@ class CsvProcessorTest : BasePlatformTestCase() { 1 kg out } inputs { - a + b + c in + a + b + c in_prod } } """.trimIndent() @@ -207,7 +207,7 @@ class CsvProcessorTest : BasePlatformTestCase() { out, actual.output ) val key = ProductValue( - "in", kg, + "in_prod", kg, ) assertEquals( QuantityValue(ops.pure(3.0), kg), actual.impacts[key] diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt index 3bbf0835e..80bfb294a 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/e2e/E2ETest.kt @@ -363,7 +363,7 @@ class E2ETest : BasePlatformTestCase() { 1 kg out } inputs { - a + b + c in + a + b + c in_prod } } """.trimIndent() @@ -399,7 +399,7 @@ class E2ETest : BasePlatformTestCase() { out, actual[0].output ) val key = ProductValue( - "in", kg, + "in_prod", kg, ) assertEquals(QuantityValue(BasicNumber(3.0), kg), actual[0].impacts[key]) } @@ -533,7 +533,7 @@ class E2ETest : BasePlatformTestCase() { 1 kg out } inputs { - 3 kg * q in + 3 kg * q in_prod } } """.trimIndent() @@ -738,7 +738,7 @@ class E2ETest : BasePlatformTestCase() { 1 kg out2 allocate 10 percent } inputs { - 1 kg in + 1 kg in_prod } } """.trimIndent() @@ -1031,12 +1031,12 @@ class E2ETest : BasePlatformTestCase() { 1 kg out } inputs { - 1 l in + 1 l in_prod } } process p2 { products { - 1 kg in + 1 kg in_prod } } """.trimIndent() @@ -1050,7 +1050,7 @@ class E2ETest : BasePlatformTestCase() { ) { Evaluator(symbolTable, ops, mockk()).trace(template) } - assertEquals("incompatible dimensions: length³ vs mass for product in", e.message) + assertEquals("incompatible dimensions: length³ vs mass for product in_prod", e.message) } private fun createFilesAndSymbols(vf: VirtualFile): SymbolTable { diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt index eafc15ed3..acd2da0d0 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaBioExchangeAnnotatorTest.kt @@ -36,7 +36,7 @@ class LcaBioExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() as LcaTerminalBioExchange + .getEmissions().first().terminalBioExchange!! val mock = AnnotationHolderMock() val annotator = LcaBioExchangeAnnotator() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt index 295290657..3336ea45c 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt @@ -34,7 +34,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() @@ -77,7 +77,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() @@ -114,7 +114,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() @@ -154,7 +154,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() @@ -199,7 +199,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() val annotator = LcaTechnoInputExchangeAnnotator() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt index 760246824..8b405ec60 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/DefaultRefFileResolverTest.kt @@ -33,7 +33,7 @@ class DefaultRefFileResolverTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val target = element .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt index 45132cdd7..611398c4b 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefCollectorScopeProcessorTest.kt @@ -57,7 +57,7 @@ class DataRefCollectorScopeProcessorTest : BasePlatformTestCase() { """.trimIndent() ) val process = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p", mapOf("d" to "LABEL")).first() - val element = process.getInputs().first() as LcaTerminalTechnoInputExchange + val element = process.getInputs().first().terminalTechnoInputExchange!! val target = element .dataExpression as LcaDataRef diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt index 586d3d09e..46cfd9a85 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefExactNameMatcherScopeProcessorTest.kt @@ -65,7 +65,7 @@ class DataRefExactNameMatcherScopeProcessorTest : ParsingTestCase("", "lca", Lca ) as LcaFile val process = file.getProcesses().first() val assignment = process.getLabelsList().first().labelAssignmentList.first() - val element = process.getInputs().first() as LcaTerminalTechnoInputExchange + val element = process.getInputs().first().terminalTechnoInputExchange!! val dataRef = element .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt index 6a8ecf37d..0afec4da7 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReferenceTest.kt @@ -70,7 +70,7 @@ class DataReferenceTest : BasePlatformTestCase() { val fqn = "$pkgName.caller" val process = ProcessStubKeyIndex.findProcesses(project, fqn).first() val element = process - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val ref = element .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt index 550dcc6ee..7c0c1075c 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt @@ -68,7 +68,7 @@ class LabelReferenceTest : BasePlatformTestCase() { ) val element = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p", - ).first().getInputs().first() as LcaTerminalTechnoInputExchange + ).first().getInputs().first().terminalTechnoInputExchange!! val ref = element .inputProductSpec.getProcessTemplateSpec()!! .getMatchLabels()!!.labelSelectorList.first() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt index cf8036b31..0beeebdee 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ParameterReferenceTest.kt @@ -49,7 +49,7 @@ class ParameterReferenceTest : BasePlatformTestCase() { ) val fqn = "$pkgName.p" val process = ProcessStubKeyIndex.findProcesses(project, fqn).first() - val element = process.getInputs().first() as LcaTerminalTechnoInputExchange + val element = process.getInputs().first().terminalTechnoInputExchange!! val ref = element .inputProductSpec .getProcessTemplateSpec()!! @@ -98,7 +98,7 @@ class ParameterReferenceTest : BasePlatformTestCase() { ) val fqn = "$pkgName.p" val process = ProcessStubKeyIndex.findProcesses(project, fqn).first() - val first = process.getInputs().first() as LcaTerminalTechnoInputExchange + val first = process.getInputs().first().terminalTechnoInputExchange!! val ref = first .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt index 029bf544b..e72821767 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessRefTest.kt @@ -60,7 +60,7 @@ class ProcessReferenceFromPsiProcessRefTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val ref = element .inputProductSpec .getProcessTemplateSpec()!! @@ -138,7 +138,7 @@ class ProcessReferenceFromPsiProcessRefTest : BasePlatformTestCase() { """.trimIndent() ) val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val ref = first .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt index 4cd146420..78a2ecae8 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ProcessReferenceFromPsiProcessTemplateSpecTest.kt @@ -59,7 +59,7 @@ class ProcessReferenceFromPsiProcessTemplateSpecTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val ref = element .inputProductSpec .getProcessTemplateSpec()!! @@ -137,7 +137,7 @@ class ProcessReferenceFromPsiProcessTemplateSpecTest : BasePlatformTestCase() { """.trimIndent() ) val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val ref = first .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt index 5a4518764..7c13744ca 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceRefTest.kt @@ -66,7 +66,7 @@ class SubstanceReferenceFromPsiSubstanceRefTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() as LcaTerminalBioExchange + .getEmissions().first().terminalBioExchange!! val ref = element .substanceSpec .getSubstanceRef() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt index 5948455b3..c199a4999 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/SubstanceReferenceFromPsiSubstanceSpecTest.kt @@ -59,7 +59,7 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() as LcaTerminalBioExchange + .getEmissions().first().terminalBioExchange!! val substanceSpec = element .getSubstanceSpec() @@ -117,7 +117,7 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getResources().first() as LcaTerminalBioExchange + .getResources().first().terminalBioExchange!! val substanceSpec = element .getSubstanceSpec() @@ -169,7 +169,7 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() as LcaTerminalBioExchange + .getEmissions().first().terminalBioExchange!! val substanceSpec = element .getSubstanceSpec() @@ -227,7 +227,7 @@ class SubstanceReferenceFromPsiSubstanceSpecTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getEmissions().first() as LcaTerminalBioExchange + .getEmissions().first().terminalBioExchange!! val spec = element .getSubstanceSpec() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt index 9ff354f08..caba54acf 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/LcaMatchLabelsEvaluatorTest.kt @@ -27,7 +27,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { """.trimIndent() ) val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = element .inputProductSpec .getProcessTemplateSpec()!! @@ -61,7 +61,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { """.trimIndent() ) val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! @@ -95,7 +95,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { """.trimIndent() ) val first = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! @@ -133,7 +133,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { "$pkgName.p", mapOf("country" to "FR") ).first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! @@ -171,7 +171,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { project, "$pkgName.p" ).first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! @@ -211,7 +211,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { project, "$pkgName.p" ).first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! @@ -246,7 +246,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { project, "$pkgName.p" ).first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! @@ -277,7 +277,7 @@ class LcaMatchLabelsEvaluatorTest : BasePlatformTestCase() { project, "$pkgName.p" ).first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val labels = first .inputProductSpec .getProcessTemplateSpec()!! diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt index 85985507b..aebf4110b 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt @@ -95,7 +95,7 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { ) val first = ProcessStubKeyIndex .findProcesses(project, "$pkgName.p", mapOf("geo" to "FR")).first() - .getInputs().first() as LcaTerminalTechnoInputExchange + .getInputs().first().terminalTechnoInputExchange!! val target = first .inputProductSpec .getProcessTemplateSpec()!! @@ -142,7 +142,7 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { """.trimIndent() ) val target = ProcessStubKeyIndex.findProcesses(project, "$pkgName.testProcess").first() - .getEmissions().first() + .getEmissions().first().terminalBioExchange!! val checker = PsiLcaTypeChecker() val expected = TBioExchange(TSubstance("testSubstance", DimensionFixture.mass, "air", null)) @@ -184,7 +184,7 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { """.trimIndent() ) val target = ProcessStubKeyIndex.findProcesses(project, "$pkgName.testProcess").first() - .getEmissions().first() + .getEmissions().first().terminalBioExchange!! val checker = PsiLcaTypeChecker() val expected = "Incompatible dimensions: expecting mass, found length³" @@ -881,7 +881,7 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { """.trimIndent() ) val target = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first().terminalTechnoInputExchange!! val checker = PsiLcaTypeChecker() // when @@ -967,7 +967,7 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { """.trimIndent() ) val target = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first().terminalTechnoInputExchange!! val checker = PsiLcaTypeChecker() // when/then @@ -1038,7 +1038,7 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { """.trimIndent() ) val target = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() - .getInputs().first() + .getInputs().first().terminalTechnoInputExchange!! val checker = PsiLcaTypeChecker() // when From 637b8fb4c7316bb7603297ca69a535f6a00d4e72 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Tue, 23 Jan 2024 12:13:44 +0100 Subject: [PATCH 08/24] data source reference and resolve --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 12 ++++- .../language/psi/manipulators/Manipulators.kt | 5 ++ .../language/psi/mixin/PsiDataSourceMixin.kt | 32 ++++++++++++ .../psi/mixin/ref/PsiDataSourceRefMixin.kt | 16 ++++++ .../psi/reference/DataSourceReference.kt | 15 ++++++ .../language/psi/stub/LcaStubIndexKeys.kt | 3 ++ .../language/psi/stub/StubIndexVersion.kt | 2 +- .../psi/stub/datasource/DataSourceStub.kt | 8 +++ .../datasource/DataSourceStubElementType.kt | 44 ++++++++++++++++ .../psi/stub/datasource/DataSourceStubImpl.kt | 15 ++++++ .../stub/datasource/DataSourceStubKeyIndex.kt | 35 +++++++++++++ .../psi/type/PsiDataSourceDefinition.kt | 11 ++++ .../language/psi/type/ref/PsiDataSourceRef.kt | 10 ++++ plugin/src/main/resources/META-INF/plugin.xml | 5 ++ .../psi/reference/DataSourceReferenceTest.kt | 52 +++++++++++++++++++ .../psi/reference/LabelReferenceTest.kt | 1 - 16 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiDataSourceMixin.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiDataSourceRefMixin.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReference.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStub.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubElementType.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubImpl.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubKeyIndex.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiDataSourceDefinition.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiDataSourceRef.kt create mode 100644 plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index 4e8f05f4a..dd92ad054 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -107,7 +107,12 @@ import ::= "import" urn { Data source */ -dataSourceDefinition ::= 'datasource' dataSourceRef '{' (locationField | schemaDefinition)* '}' +dataSourceDefinition ::= 'datasource' dataSourceRef '{' (locationField | schemaDefinition)* '}' { + implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiDataSourceDefinition"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiDataSourceMixin" + elementTypeClass="ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStubElementType" + stubClass = "ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStub" +} locationField ::= 'location' '=' STRING_LITERAL schemaDefinition ::= 'schema' '{' columnDefinition* '}' columnDefinition ::= STRING_LITERAL '=' dataExpression @@ -362,7 +367,10 @@ testRef ::= uid { mixin="ch.kleis.lcaac.plugin.language.psi.mixin.ref.PsiTestRefMixin" } -dataSourceRef ::= uid +dataSourceRef ::= uid { + implements=["ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataSourceRef"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.ref.PsiDataSourceRefMixin" +} /* Spec diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt index fe6d9cf8f..08638ca8a 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt @@ -1,6 +1,7 @@ package ch.kleis.lcaac.plugin.language.psi.manipulators import ch.kleis.lcaac.plugin.language.psi.type.PsiAssignment +import ch.kleis.lcaac.plugin.language.psi.type.PsiDataSourceDefinition import ch.kleis.lcaac.plugin.language.psi.type.PsiGlobalAssignment import ch.kleis.lcaac.plugin.language.psi.type.PsiLabelAssignment import ch.kleis.lcaac.plugin.language.psi.type.ref.* @@ -27,6 +28,7 @@ class PsiProcessTemplateRefManipulator : PsiUIDOwnerManipulator() class PsiLabelRefManipulator : PsiUIDOwnerManipulator() class PsiParameterRefManipulator : PsiUIDOwnerManipulator() class PsiProductRefManipulator : PsiUIDOwnerManipulator() +class PsiDataSourceRefManipulator : PsiUIDOwnerManipulator() sealed class PsiDelegateManipulator( private val getter: (E) -> PsiUIDOwner @@ -64,3 +66,6 @@ class PsiGlobalAssignmentManipulator : PsiDelegateManipulator( { it.getDataRef() } ) +class PsiDataSourceManipulator : PsiDelegateManipulator( + { it.getDataSourceRef() } +) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiDataSourceMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiDataSourceMixin.kt new file mode 100644 index 000000000..a3d07e723 --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiDataSourceMixin.kt @@ -0,0 +1,32 @@ +package ch.kleis.lcaac.plugin.language.psi.mixin + +import ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStub +import ch.kleis.lcaac.plugin.psi.LcaDataSourceDefinition +import ch.kleis.lcaac.plugin.psi.LcaDataSourceRef +import com.intellij.extapi.psi.StubBasedPsiElementBase +import com.intellij.lang.ASTNode +import com.intellij.psi.PsiElement +import com.intellij.psi.stubs.IStubElementType +import com.intellij.psi.util.PsiTreeUtil + +abstract class PsiDataSourceMixin : StubBasedPsiElementBase, LcaDataSourceDefinition { + constructor(node: ASTNode) : super(node) + constructor(stub: DataSourceStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType) + + override fun getDataSourceRef(): LcaDataSourceRef { + return PsiTreeUtil.findChildrenOfType(this, LcaDataSourceRef::class.java).elementAt(0) + } + + override fun getName(): String { + return getDataSourceRef().name + } + + override fun setName(name: String): PsiElement { + getDataSourceRef().name = name + return this + } + + override fun getNameIdentifier(): PsiElement? { + return getDataSourceRef().nameIdentifier + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiDataSourceRefMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiDataSourceRefMixin.kt new file mode 100644 index 000000000..507e99cfa --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiDataSourceRefMixin.kt @@ -0,0 +1,16 @@ +package ch.kleis.lcaac.plugin.language.psi.mixin.ref + +import ch.kleis.lcaac.plugin.language.psi.reference.DataSourceReference +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataSourceRef +import com.intellij.extapi.psi.ASTWrapperPsiElement +import com.intellij.lang.ASTNode + +abstract class PsiDataSourceRefMixin(node: ASTNode) : ASTWrapperPsiElement(node), PsiDataSourceRef { + override fun getReference(): DataSourceReference { + return super.getReference() + } + + override fun getName(): String { + return super.getName() + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReference.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReference.kt new file mode 100644 index 000000000..6d6fcb6ce --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReference.kt @@ -0,0 +1,15 @@ +package ch.kleis.lcaac.plugin.language.psi.reference + +import ch.kleis.lcaac.plugin.language.psi.stub.LcaStubIndexKeys +import ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStubKeyIndex +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataSourceRef +import ch.kleis.lcaac.plugin.psi.LcaDataSourceDefinition +import com.intellij.psi.stubs.StubIndex + +class DataSourceReference( + element: PsiDataSourceRef +) : GlobalUIDOwnerReference( + element, + { project, fqn -> DataSourceStubKeyIndex.findDataSources(project, fqn) }, + { project -> StubIndex.getInstance().getAllKeys(LcaStubIndexKeys.DATA_SOURCES, project) } +) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/LcaStubIndexKeys.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/LcaStubIndexKeys.kt index b747b5697..ee3cd190f 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/LcaStubIndexKeys.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/LcaStubIndexKeys.kt @@ -23,4 +23,7 @@ object LcaStubIndexKeys { val GLOBAL_ASSIGNMENTS: StubIndexKey = StubIndexKey.createIndexKey("lca.globalAssignments") + + val DATA_SOURCES: StubIndexKey = + StubIndexKey.createIndexKey("lca.dataSources") } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/StubIndexVersion.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/StubIndexVersion.kt index 6db4ff75a..a528118e2 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/StubIndexVersion.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/StubIndexVersion.kt @@ -3,4 +3,4 @@ package ch.kleis.lcaac.plugin.language.psi.stub /** * Should be incremented when the stub structure is modified. */ -const val stubIndexVersion: Int = 7 +const val stubIndexVersion: Int = 8 diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStub.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStub.kt new file mode 100644 index 000000000..4d1ffde63 --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStub.kt @@ -0,0 +1,8 @@ +package ch.kleis.lcaac.plugin.language.psi.stub.datasource + +import ch.kleis.lcaac.plugin.psi.LcaDataSourceDefinition +import com.intellij.psi.stubs.StubElement + +interface DataSourceStub : StubElement { + val fqn: String +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubElementType.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubElementType.kt new file mode 100644 index 000000000..b03593a47 --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubElementType.kt @@ -0,0 +1,44 @@ +package ch.kleis.lcaac.plugin.language.psi.stub.datasource + +import ch.kleis.lcaac.plugin.LcaLanguage +import ch.kleis.lcaac.plugin.language.psi.stub.LcaStubIndexKeys +import ch.kleis.lcaac.plugin.psi.LcaDataSourceDefinition +import ch.kleis.lcaac.plugin.psi.impl.LcaDataSourceDefinitionImpl +import com.intellij.lang.LighterAST +import com.intellij.lang.LighterASTNode +import com.intellij.psi.PsiElement +import com.intellij.psi.stubs.* + +class DataSourceStubElementType(debugName: String) : + ILightStubElementType(debugName, LcaLanguage.INSTANCE) { + override fun getExternalId(): String { + return "lca.${super.toString()}" + } + + @Suppress("UNCHECKED_CAST") + override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): DataSourceStub { + return DataSourceStubImpl(parentStub as StubElement, dataStream.readNameString()!!) + } + + override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): DataSourceStub { + throw UnsupportedOperationException("cannot create process stub from lighter ast node") + } + + @Suppress("UNCHECKED_CAST") + override fun createStub(psi: LcaDataSourceDefinition, parentStub: StubElement?): DataSourceStub { + val fqn = psi.getDataSourceRef().getFullyQualifiedName() + return DataSourceStubImpl(parentStub as StubElement, fqn) + } + + override fun createPsi(stub: DataSourceStub): LcaDataSourceDefinition { + return LcaDataSourceDefinitionImpl(stub, this) + } + + override fun indexStub(stub: DataSourceStub, sink: IndexSink) { + sink.occurrence(LcaStubIndexKeys.DATA_SOURCES, stub.fqn) + } + + override fun serialize(stub: DataSourceStub, dataStream: StubOutputStream) { + dataStream.writeName(stub.fqn) + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubImpl.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubImpl.kt new file mode 100644 index 000000000..8b9606cef --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubImpl.kt @@ -0,0 +1,15 @@ +package ch.kleis.lcaac.plugin.language.psi.stub.datasource + +import ch.kleis.lcaac.plugin.psi.LcaDataSourceDefinition +import ch.kleis.lcaac.plugin.psi.LcaTypes +import com.intellij.psi.stubs.IStubElementType +import com.intellij.psi.stubs.StubBase +import com.intellij.psi.stubs.StubElement + +class DataSourceStubImpl( + parent: StubElement, + override val fqn: String, +) : StubBase( + parent, + LcaTypes.DATA_SOURCE_DEFINITION as IStubElementType, *> +), DataSourceStub diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubKeyIndex.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubKeyIndex.kt new file mode 100644 index 000000000..1de6e396d --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/stub/datasource/DataSourceStubKeyIndex.kt @@ -0,0 +1,35 @@ +package ch.kleis.lcaac.plugin.language.psi.stub.datasource + +import ch.kleis.lcaac.plugin.language.psi.stub.LcaStubIndexKeys +import ch.kleis.lcaac.plugin.language.psi.stub.stubIndexVersion +import ch.kleis.lcaac.plugin.psi.LcaDataSourceDefinition +import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.StringStubIndexExtension +import com.intellij.psi.stubs.StubIndex +import com.intellij.psi.stubs.StubIndexKey + +class DataSourceStubKeyIndex : StringStubIndexExtension() { + override fun getKey(): StubIndexKey { + return LcaStubIndexKeys.DATA_SOURCES + } + + override fun getVersion(): Int { + return stubIndexVersion + } + + companion object { + fun findDataSources( + project: Project, + fqn: String, + scope: GlobalSearchScope = GlobalSearchScope.allScope(project), + ): Collection = + StubIndex.getElements( + LcaStubIndexKeys.DATA_SOURCES, + fqn, + project, + scope, + LcaDataSourceDefinition::class.java + ) + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiDataSourceDefinition.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiDataSourceDefinition.kt new file mode 100644 index 000000000..bde21e77e --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiDataSourceDefinition.kt @@ -0,0 +1,11 @@ +package ch.kleis.lcaac.plugin.language.psi.type + +import ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStub +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataSourceRef +import com.intellij.psi.PsiNameIdentifierOwner +import com.intellij.psi.StubBasedPsiElement + +interface PsiDataSourceDefinition : StubBasedPsiElement, PsiNameIdentifierOwner { + override fun getName(): String + fun getDataSourceRef(): PsiDataSourceRef +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiDataSourceRef.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiDataSourceRef.kt new file mode 100644 index 000000000..5cd4caa8c --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiDataSourceRef.kt @@ -0,0 +1,10 @@ +package ch.kleis.lcaac.plugin.language.psi.type.ref + +import ch.kleis.lcaac.plugin.language.psi.reference.DataSourceReference +import ch.kleis.lcaac.plugin.language.psi.type.trait.PsiUIDOwner + +interface PsiDataSourceRef : PsiUIDOwner { + override fun getReference(): DataSourceReference { + return DataSourceReference(this) + } +} diff --git a/plugin/src/main/resources/META-INF/plugin.xml b/plugin/src/main/resources/META-INF/plugin.xml index e367b7474..c2f39a6b1 100644 --- a/plugin/src/main/resources/META-INF/plugin.xml +++ b/plugin/src/main/resources/META-INF/plugin.xml @@ -76,10 +76,14 @@ implementationClass="ch.kleis.lcaac.plugin.language.psi.manipulators.PsiGlobalAssignmentManipulator"/> + + + diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt new file mode 100644 index 000000000..81bb2e176 --- /dev/null +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt @@ -0,0 +1,52 @@ +package ch.kleis.lcaac.plugin.language.psi.reference + +import ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStubKeyIndex +import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import com.intellij.testFramework.fixtures.BasePlatformTestCase +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class DataSourceReferenceTest: BasePlatformTestCase() { + override fun getTestDataPath(): String { + return "" + } + + @Test + fun test_resolve_whenDataSource() { + // given + val pkgName = {}.javaClass.enclosingMethod.name + myFixture.createFile("$pkgName.lca", """ + package $pkgName + + datasource inventory { + location = "inventory.csv" + schema { + "mass" = 1 kg + } + } + + process p { + params { + row from inventory + } + } + """.trimIndent()) + val dataSource = DataSourceStubKeyIndex.findDataSources( + project, "$pkgName.inventory" + ).first() + val ref = ProcessStubKeyIndex.findProcesses( + project, "$pkgName.p" + ).first() + .paramsList.first() + .assignmentList.first() + .dataSourceRef!! + + // when + val actual = ref.reference.resolve() + + // then + assertEquals(dataSource, actual) + } +} diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt index 7c0c1075c..1fd9cbf63 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/LabelReferenceTest.kt @@ -1,7 +1,6 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex -import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.testFramework.fixtures.BasePlatformTestCase import org.junit.Test import org.junit.runner.RunWith From 78b00432533c4be2546a6b2c9767d4b680571429 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Tue, 23 Jan 2024 12:28:37 +0100 Subject: [PATCH 09/24] bnf: column ref in schema definition --- plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index dd92ad054..aa53db00e 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -115,7 +115,7 @@ dataSourceDefinition ::= 'datasource' dataSourceRef '{' (locationField | schemaD } locationField ::= 'location' '=' STRING_LITERAL schemaDefinition ::= 'schema' '{' columnDefinition* '}' -columnDefinition ::= STRING_LITERAL '=' dataExpression +columnDefinition ::= columnRef '=' dataExpression /* Global variables From 6eab36043474651d07640205d14460e2909f3c93 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Tue, 23 Jan 2024 13:06:26 +0100 Subject: [PATCH 10/24] lcaac bump version: 1.4-rc -> 1.4.0 --- plugin/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index efd897bf7..a2457bc5c 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -47,7 +47,7 @@ sourceSets { } dependencies { - implementation("ch.kleis.lcaac:core:1.4-rc") + implementation("ch.kleis.lcaac:core:1.4.0") implementation(files(layout.buildDirectory.dir("stdlib/ef3.1")) { builtBy("generateEmissionFactors31") From 2cdbdfabdc5496d3d18a0cb2f1a1c4b103ce31ce Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Fri, 26 Jan 2024 17:55:13 +0100 Subject: [PATCH 11/24] bump version 1.4.0 -> 1.5.0 --- plugin/build.gradle.kts | 2 +- .../ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index a2457bc5c..48f2cd293 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -47,7 +47,7 @@ sourceSets { } dependencies { - implementation("ch.kleis.lcaac:core:1.4.0") + implementation("ch.kleis.lcaac:core:1.5.0") implementation(files(layout.buildDirectory.dir("stdlib/ef3.1")) { builtBy("generateEmissionFactors31") diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt index 7b499e946..026157fd8 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt @@ -125,7 +125,7 @@ class LcaMapper( indicatorSpec(it.indicatorRef), ) ) - } ?: EImpactBlockForEach("", "", emptyMap(), emptyList()) + } ?: EImpactBlockForEach("", EDataSourceRef(""), emptyMap(), emptyList()) } private fun indicatorSpec(variable: PsiIndicatorRef): EIndicatorSpec { @@ -142,7 +142,7 @@ class LcaMapper( inputProductSpec(it.inputProductSpec), ) ) - } ?: ETechnoBlockForEach("", "", emptyMap(), emptyList()) + } ?: ETechnoBlockForEach("", EDataSourceRef(""), emptyMap(), emptyList()) } private fun outputProductSpec( @@ -207,7 +207,7 @@ class LcaMapper( substanceSpec(it.substanceSpec, quantity, symbolTable) ) ) - } ?: EBioBlockForEach("", "", emptyMap(), emptyList()) + } ?: EBioBlockForEach("", EDataSourceRef(""), emptyMap(), emptyList()) } fun dataExpression(dataExpression: LcaDataExpression): DataExpression { From 21bdf1141e04f0e62fe67223cfd72e32b8b21dcc Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sat, 27 Jan 2024 18:08:09 +0100 Subject: [PATCH 12/24] bnf: refactor to match grammar:1.5.0 --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 31 +++++++++++++------ .../ch/kleis/lcaac/plugin/language/Lca.flex | 2 +- .../ide/syntax/LcaSyntaxHighlighter.kt | 4 +-- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index aa53db00e..e76749ecf 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -55,8 +55,8 @@ LOCATION_KEYWORD = 'location' SCHEMA_KEYWORD = 'schema' FOR_EACH_KEYWORD = 'for_each' - IN_KEYWORD = 'in' SUM_KEYWORD = 'sum' + LOOKUP_KEYWORD = 'lookup' NUMBER = 'number' LSQBRACE = '[' @@ -268,7 +268,7 @@ block_impacts ::= "impacts" "{" impactExchange* "}" technoProductExchange ::= dataExpression outputProductSpec technoInputExchange ::= terminalTechnoInputExchange - | 'for_each' dataRef 'in' dataSourceRef '{' (variables | technoInputExchange)* '}' + | 'for_each' dataRef 'from' dataSourceRef '{' (variables | technoInputExchange)* '}' terminalTechnoInputExchange ::= dataExpression inputProductSpec bioExchange ::= terminalBioExchange | 'for_each' dataRef 'in' dataSourceRef '{' (variables | bioExchange)* '}' @@ -282,10 +282,12 @@ terminalImpactExchange ::= dataExpression indicatorRef Use GrammarKit's expression-related syntax and rules to generate a Pratt parser. */ -dataExpression ::= addGroup - | mulGroup - | exponentialQuantityExpression - | baseGroup +dataExpression ::= exponentialQuantityExpression + | mulGroup + | addGroup + | baseGroup + | recordExpression + | colExpression private addGroup ::= addQuantityExpression | subQuantityExpression private mulGroup ::= scaleQuantityExpression | mulQuantityExpression | divQuantityExpression @@ -307,9 +309,18 @@ exponentialQuantityExpression ::= dataExpression "^" NUMBER { extends=dataExpres parenQuantityExpression ::= "(" dataExpression ")" { extends=dataExpression } scaleQuantityExpression ::= NUMBER dataExpression { extends=dataExpression methods=[scale="NUMBER"]} stringExpression ::= STRING_LITERAL { extends=dataExpression } -columnRef ::= STRING_LITERAL -sliceExpression ::= dataRef '[' columnRef ']' { extends=dataExpression } -colExpression ::= 'sum' '(' dataSourceRef ',' columnRef ('*' columnRef)* ')' { extends=dataExpression } +sliceExpression ::= dataRef '.' columnRef { extends=dataExpression } +recordExpression ::= 'lookup' dataSourceExpression { extends=dataExpression } +colExpression ::= 'sum' '(' dataSourceExpression ',' columnRef ('*' columnRef)* ')' { extends=dataExpression } + +/* + Data source expression + */ + +dataSourceExpression ::= dataSourceRef rowFilter? +rowFilter ::= MATCH_KEYWORD rowSelector + | MATCH_KEYWORD LPAREN ( rowSelector (COMMA rowSelector)* COMMA? ) RPAREN +rowSelector ::= columnRef EQUAL dataExpression /* @@ -372,6 +383,8 @@ dataSourceRef ::= uid { mixin="ch.kleis.lcaac.plugin.language.psi.mixin.ref.PsiDataSourceRefMixin" } +columnRef ::= uid + /* Spec */ diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex index f80b06627..2aad14f26 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex @@ -102,8 +102,8 @@ CommentContent = .* "location" { return LcaTypes.LOCATION_KEYWORD; } "schema" { return LcaTypes.SCHEMA_KEYWORD; } "for_each" { return LcaTypes.FOR_EACH_KEYWORD; } - "in" { return LcaTypes.IN_KEYWORD; } "sum" { return LcaTypes.SUM_KEYWORD; } + "lookup" { return LcaTypes.LOOKUP_KEYWORD; } [-]?{Number_Int} ("." {Number_Int}? )? {Number_Exp}? { return LcaTypes.NUMBER; } {Identifier} { return LcaTypes.IDENTIFIER; } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt index 209687bfc..20ea04b7b 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt @@ -46,7 +46,7 @@ class LcaSyntaxHighlighter : SyntaxHighlighterBase() { PRODUCTS_KEYWORD, INPUTS_KEYWORD, EMISSIONS_KEYWORD, RESOURCES_KEYWORD, TEST_KEYWORD, GIVEN_KEYWORD, ASSERT_KEYWORD, BETWEEN_KEYWORD, AND_KEYWORD, - DATASOURCE_KEYWORD, SCHEMA_KEYWORD, FOR_EACH_KEYWORD, IN_KEYWORD -> KEYWORD_KEYS + DATASOURCE_KEYWORD, SCHEMA_KEYWORD, FOR_EACH_KEYWORD -> KEYWORD_KEYS IDENTIFIER -> IDENTIFIER_KEYS @@ -56,7 +56,7 @@ class LcaSyntaxHighlighter : SyntaxHighlighterBase() { REFERENCE_UNIT_KEYWORD, SYMBOL_KEYWORD, NAME_KEYWORD, TYPE_KEYWORD, COMPARTMENT_KEYWORD, SUB_COMPARTMENT_KEYWORD, - LOCATION_KEYWORD, SUM_KEYWORD -> FIELD_KEYS + LOCATION_KEYWORD, SUM_KEYWORD, LOOKUP_KEYWORD -> FIELD_KEYS TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS From 4b1929b5f638009e91b2365e8ce895e736db2f18 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sat, 27 Jan 2024 19:23:42 +0100 Subject: [PATCH 13/24] refs and resolve: data source refs, block for each, column references --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 31 +++- .../lcaac/plugin/language/psi/LcaFile.kt | 4 + .../language/psi/manipulators/Manipulators.kt | 23 +-- .../psi/mixin/PsiBlockForEachMixin.kt | 51 +++++++ .../psi/mixin/PsiColumnDefinitionMixin.kt | 32 ++++ .../psi/mixin/ref/PsiColumnRefMixin.kt | 18 +++ .../language/psi/reference/ColumnReference.kt | 88 +++++++++++ .../psi/reference/DataRefScopeProcessor.kt | 4 + .../language/psi/reference/DataReference.kt | 7 +- .../language/psi/type/PsiBlockForEach.kt | 16 ++ .../language/psi/type/PsiColumnDefinition.kt | 11 ++ .../language/psi/type/ref/PsiColumnRef.kt | 10 ++ plugin/src/main/resources/META-INF/plugin.xml | 8 +- ...taRefExactNameMatcherScopeProcessorTest.kt | 75 ++++++++- .../psi/reference/DataReferenceTest.kt | 143 ++++++++++++++++-- .../psi/reference/quantity/my_units.lca | 11 -- .../psi/reference/quantity/test_resolve.lca | 10 -- .../test_resolve_whenFromGlobalAssignment.lca | 13 -- .../test_resolve_whenFromProcessParameter.lca | 19 --- .../test_resolve_whenFromUnitDefinition.lca | 13 -- 20 files changed, 486 insertions(+), 101 deletions(-) create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiColumnRefMixin.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ColumnReference.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiBlockForEach.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiColumnDefinition.kt create mode 100644 plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiColumnRef.kt delete mode 100644 plugin/testdata/language/psi/reference/quantity/my_units.lca delete mode 100644 plugin/testdata/language/psi/reference/quantity/test_resolve.lca delete mode 100644 plugin/testdata/language/psi/reference/quantity/test_resolve_whenFromGlobalAssignment.lca delete mode 100644 plugin/testdata/language/psi/reference/quantity/test_resolve_whenFromProcessParameter.lca delete mode 100644 plugin/testdata/language/psi/reference/quantity/test_resolve_whenFromUnitDefinition.lca diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index e76749ecf..042a09cd0 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -115,7 +115,10 @@ dataSourceDefinition ::= 'datasource' dataSourceRef '{' (locationField | schemaD } locationField ::= 'location' '=' STRING_LITERAL schemaDefinition ::= 'schema' '{' columnDefinition* '}' -columnDefinition ::= columnRef '=' dataExpression +columnDefinition ::= columnRef '=' dataExpression { + implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiColumnDefinition"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiColumnDefinitionMixin" +} /* Global variables @@ -267,15 +270,30 @@ block_impacts ::= "impacts" "{" impactExchange* "}" */ technoProductExchange ::= dataExpression outputProductSpec + technoInputExchange ::= terminalTechnoInputExchange - | 'for_each' dataRef 'from' dataSourceRef '{' (variables | technoInputExchange)* '}' + | technoBlockForEach terminalTechnoInputExchange ::= dataExpression inputProductSpec +technoBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | technoInputExchange)* '}' { + implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiBlockForEachMixin" +} + bioExchange ::= terminalBioExchange - | 'for_each' dataRef 'in' dataSourceRef '{' (variables | bioExchange)* '}' + | bioBlockForEach terminalBioExchange ::= dataExpression substanceSpec +bioBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | bioExchange)* '}' { + implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiBlockForEachMixin" +} + impactExchange ::= terminalImpactExchange - | 'for_each' dataRef 'in' dataSourceRef '{' (variables | impactExchange)* '}' + | impactBlockForEach terminalImpactExchange ::= dataExpression indicatorRef +impactBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | impactExchange)* '}' { + implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiBlockForEachMixin" +} /* Quantity @@ -383,7 +401,10 @@ dataSourceRef ::= uid { mixin="ch.kleis.lcaac.plugin.language.psi.mixin.ref.PsiDataSourceRefMixin" } -columnRef ::= uid +columnRef ::= uid { + implements=["ch.kleis.lcaac.plugin.language.psi.type.ref.PsiColumnRef"] + mixin="ch.kleis.lcaac.plugin.language.psi.mixin.ref.PsiColumnRefMixin" +} /* Spec diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/LcaFile.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/LcaFile.kt index 55d03a1b3..b69f1462e 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/LcaFile.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/LcaFile.kt @@ -67,6 +67,10 @@ class LcaFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, LcaLan return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaGlobalVariables::class.java) } + fun getDataSourceDefinitions(): Collection { + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataSourceDefinition::class.java) + } + override fun processDeclarations( processor: PsiScopeProcessor, state: ResolveState, diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt index 08638ca8a..a83d6e6b1 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/manipulators/Manipulators.kt @@ -1,16 +1,12 @@ package ch.kleis.lcaac.plugin.language.psi.manipulators -import ch.kleis.lcaac.plugin.language.psi.type.PsiAssignment -import ch.kleis.lcaac.plugin.language.psi.type.PsiDataSourceDefinition -import ch.kleis.lcaac.plugin.language.psi.type.PsiGlobalAssignment -import ch.kleis.lcaac.plugin.language.psi.type.PsiLabelAssignment +import ch.kleis.lcaac.plugin.language.psi.type.* import ch.kleis.lcaac.plugin.language.psi.type.ref.* -import ch.kleis.lcaac.plugin.language.psi.type.spec.PsiInputProductSpec -import ch.kleis.lcaac.plugin.language.psi.type.spec.PsiOutputProductSpec -import ch.kleis.lcaac.plugin.language.psi.type.spec.PsiProcessTemplateSpec -import ch.kleis.lcaac.plugin.language.psi.type.spec.PsiSubstanceSpec import ch.kleis.lcaac.plugin.language.psi.type.trait.PsiUIDOwner -import ch.kleis.lcaac.plugin.psi.* +import ch.kleis.lcaac.plugin.psi.LcaInputProductSpec +import ch.kleis.lcaac.plugin.psi.LcaOutputProductSpec +import ch.kleis.lcaac.plugin.psi.LcaProcessTemplateSpec +import ch.kleis.lcaac.plugin.psi.LcaSubstanceSpec import com.intellij.openapi.util.TextRange import com.intellij.psi.AbstractElementManipulator import com.intellij.psi.PsiElement @@ -22,13 +18,14 @@ sealed class PsiUIDOwnerManipulator : AbstractElementManipulato } } -class PsiQuantityRefManipulator : PsiUIDOwnerManipulator() +class PsiDataRefManipulator : PsiUIDOwnerManipulator() class PsiSubstanceRefManipulator : PsiUIDOwnerManipulator() class PsiProcessTemplateRefManipulator : PsiUIDOwnerManipulator() class PsiLabelRefManipulator : PsiUIDOwnerManipulator() class PsiParameterRefManipulator : PsiUIDOwnerManipulator() class PsiProductRefManipulator : PsiUIDOwnerManipulator() class PsiDataSourceRefManipulator : PsiUIDOwnerManipulator() +class PsiColumnRefManipulator : PsiUIDOwnerManipulator() sealed class PsiDelegateManipulator( private val getter: (E) -> PsiUIDOwner @@ -69,3 +66,9 @@ class PsiAssignmentManipulator : PsiDelegateManipulator( class PsiDataSourceManipulator : PsiDelegateManipulator( { it.getDataSourceRef() } ) +class PsiColumnDefinitionManipulator : PsiDelegateManipulator( + { it.getColumnRef() } +) +class PsiBlockForEachManipulator : PsiDelegateManipulator( + { it.getDataRef() } +) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt new file mode 100644 index 000000000..fe7fe1f04 --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt @@ -0,0 +1,51 @@ +package ch.kleis.lcaac.plugin.language.psi.mixin + +import ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach +import ch.kleis.lcaac.plugin.psi.* +import com.intellij.extapi.psi.ASTWrapperPsiElement +import com.intellij.lang.ASTNode +import com.intellij.psi.PsiElement +import com.intellij.psi.ResolveState +import com.intellij.psi.scope.PsiScopeProcessor +import com.intellij.psi.util.PsiTreeUtil + +abstract class PsiBlockForEachMixin(node: ASTNode) : ASTWrapperPsiElement(node), PsiBlockForEach { + override fun getDataRef(): LcaDataRef { + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataRef::class.java).elementAt(0) + } + + override fun getValue(): LcaDataSourceExpression { + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataSourceExpression::class.java).elementAt(1) + } + + override fun getName(): String { + return getDataRef().name + } + + override fun setName(name: String): PsiElement { + getDataRef().name = name + return this + } + + override fun getNameIdentifier(): PsiElement? { + return getDataRef().nameIdentifier + } + + override fun processDeclarations( + processor: PsiScopeProcessor, + state: ResolveState, + lastParent: PsiElement?, + place: PsiElement + ): Boolean { + for (block in getVariablesList()) { + if (!processor.execute(block, state)) { + return false + } + } + return processor.execute(this, state) + } + + override fun getVariablesList(): Collection { + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaVariables::class.java) + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt new file mode 100644 index 000000000..3b920fb9f --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt @@ -0,0 +1,32 @@ +package ch.kleis.lcaac.plugin.language.psi.mixin + +import ch.kleis.lcaac.plugin.psi.LcaColumnDefinition +import ch.kleis.lcaac.plugin.psi.LcaColumnRef +import ch.kleis.lcaac.plugin.psi.LcaDataExpression +import com.intellij.extapi.psi.ASTWrapperPsiElement +import com.intellij.lang.ASTNode +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil + +abstract class PsiColumnDefinitionMixin(node: ASTNode) : ASTWrapperPsiElement(node), LcaColumnDefinition { + override fun getColumnRef(): LcaColumnRef { + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaColumnRef::class.java).elementAt(0) + } + + override fun getValue(): LcaDataExpression { + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataExpression::class.java).elementAt(1) + } + + override fun getName(): String { + return getColumnRef().name + } + + override fun setName(name: String): PsiElement { + getColumnRef().name = name + return this + } + + override fun getNameIdentifier(): PsiElement? { + return getColumnRef().nameIdentifier + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiColumnRefMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiColumnRefMixin.kt new file mode 100644 index 000000000..35a541737 --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/ref/PsiColumnRefMixin.kt @@ -0,0 +1,18 @@ +package ch.kleis.lcaac.plugin.language.psi.mixin.ref + +import ch.kleis.lcaac.plugin.language.psi.reference.ColumnReference +import ch.kleis.lcaac.plugin.language.psi.reference.DataReference +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiColumnRef +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataRef +import com.intellij.extapi.psi.ASTWrapperPsiElement +import com.intellij.lang.ASTNode + +abstract class PsiColumnRefMixin(node: ASTNode) : ASTWrapperPsiElement(node), PsiColumnRef { + override fun getReference(): ColumnReference { + return super.getReference() + } + + override fun getName(): String { + return super.getName() + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ColumnReference.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ColumnReference.kt new file mode 100644 index 000000000..d70e8fcef --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/ColumnReference.kt @@ -0,0 +1,88 @@ +package ch.kleis.lcaac.plugin.language.psi.reference + +import ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiColumnRef +import ch.kleis.lcaac.plugin.psi.* +import com.intellij.codeInsight.lookup.LookupElementBuilder +import com.intellij.psi.PsiElementResolveResult +import com.intellij.psi.PsiNameIdentifierOwner +import com.intellij.psi.PsiPolyVariantReferenceBase +import com.intellij.psi.ResolveResult +import com.intellij.psi.util.PsiTreeUtil + +// TODO: Test me +class ColumnReference( + element: PsiColumnRef +) : PsiPolyVariantReferenceBase(element) { + override fun multiResolve(incompleteCode: Boolean): Array { + val localMatches = resolveColumnsMatching { it == element.name } + return localMatches.map { PsiElementResolveResult(it) }.toTypedArray() + } + + override fun getVariants(): Array { + val localDefns = resolveColumnsMatching { true } + .mapNotNull { psi -> + psi.name?.let { + LookupElementBuilder.create(it) + } + } + return localDefns.toTypedArray() + } + + private fun resolveColumnsMatching( + predicate: (String) -> Boolean + ): Set { + return when (val parent = element.parent) { + is LcaSliceExpression -> { + resolveUntilRecordExpression(parent.dataRef) + ?.let { checkDataSourceExpression(it, predicate) } + ?: emptySet() + } + + is LcaColExpression -> checkDataSourceExpression(parent.dataSourceExpression, predicate) + is LcaRowSelector -> { + val dataSourceExpression = PsiTreeUtil.getParentOfType(parent, LcaDataSourceExpression::class.java) + ?: return emptySet() + checkDataSourceExpression(dataSourceExpression, predicate) + } + + else -> emptySet() + } + } + + private fun resolveUntilRecordExpression(ref: LcaDataRef): LcaDataSourceExpression? { + val target = ref.reference.resolve() ?: return null + return when (target) { + is LcaAssignment -> { + when (val value = target.getValue()) { + is LcaRecordExpression -> value.dataSourceExpression + is LcaDataRef -> resolveUntilRecordExpression(value) + else -> null + } + } + + is LcaGlobalAssignment -> { + when (val value = target.getValue()) { + is LcaRecordExpression -> value.dataSourceExpression + is LcaDataRef -> resolveUntilRecordExpression(value) + else -> null + } + } + + is PsiBlockForEach -> target.getValue() + else -> null + } + } + + private fun checkDataSourceExpression(expression: LcaDataSourceExpression, predicate: (String) -> Boolean): Set { + val ds = expression + .dataSourceRef.reference.resolve() as LcaDataSourceDefinition? + ?: return emptySet() + val schema = ds.schemaDefinitionList + .firstOrNull() ?: return emptySet() + val columns = schema + .columnDefinitionList + .filter { predicate(it.name) } + return columns.toSet() + } +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefScopeProcessor.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefScopeProcessor.kt index bfd7d711d..0668f8fa8 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefScopeProcessor.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataRefScopeProcessor.kt @@ -1,5 +1,6 @@ package ch.kleis.lcaac.plugin.language.psi.reference +import ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataRef import ch.kleis.lcaac.plugin.psi.LcaLabels import ch.kleis.lcaac.plugin.psi.LcaParams @@ -53,6 +54,9 @@ class DataRefExactNameMatcherScopeProcessor( return checkDecl(element.labelAssignmentList) } + if (element is PsiBlockForEach) { + return checkDecl(listOf(element)) + } return true } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReference.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReference.kt index 7218a12ea..8dc7335aa 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReference.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataReference.kt @@ -12,7 +12,7 @@ import com.intellij.psi.util.PsiTreeUtil class DataReference( element: PsiDataRef -) : PsiReferenceBase(element), PsiPolyVariantReference { +) : PsiPolyVariantReferenceBase(element) { private val globalAssignmentRef = GlobalUIDOwnerReference( element, { project, fqn -> @@ -32,11 +32,6 @@ class DataReference( } ) - override fun resolve(): PsiElement? { - val results = multiResolve(false).mapNotNull { it.element } - return if (results.size == 1) results.first() else null - } - override fun multiResolve(incompleteCode: Boolean): Array { val localMatches = resolveElementLocally( DataRefExactNameMatcherScopeProcessor(element) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiBlockForEach.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiBlockForEach.kt new file mode 100644 index 000000000..bcb2866bc --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiBlockForEach.kt @@ -0,0 +1,16 @@ +package ch.kleis.lcaac.plugin.language.psi.type + +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataRef +import ch.kleis.lcaac.plugin.psi.LcaDataSourceExpression +import ch.kleis.lcaac.plugin.psi.LcaVariables +import com.intellij.psi.PsiNameIdentifierOwner + +interface PsiBlockForEach : PsiNameIdentifierOwner { + override fun getName(): String + + fun getDataRef(): PsiDataRef + + fun getValue(): LcaDataSourceExpression + + fun getVariablesList(): Collection +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiColumnDefinition.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiColumnDefinition.kt new file mode 100644 index 000000000..7721da37d --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/PsiColumnDefinition.kt @@ -0,0 +1,11 @@ +package ch.kleis.lcaac.plugin.language.psi.type + +import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiColumnRef +import ch.kleis.lcaac.plugin.psi.LcaDataExpression +import com.intellij.psi.PsiNameIdentifierOwner + +interface PsiColumnDefinition : PsiNameIdentifierOwner { + override fun getName(): String + fun getColumnRef(): PsiColumnRef + fun getValue(): LcaDataExpression +} diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiColumnRef.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiColumnRef.kt new file mode 100644 index 000000000..c0ed954e7 --- /dev/null +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/type/ref/PsiColumnRef.kt @@ -0,0 +1,10 @@ +package ch.kleis.lcaac.plugin.language.psi.type.ref + +import ch.kleis.lcaac.plugin.language.psi.reference.ColumnReference +import ch.kleis.lcaac.plugin.language.psi.type.trait.PsiUIDOwner + +interface PsiColumnRef : PsiUIDOwner { + override fun getReference(): ColumnReference { + return ColumnReference(this) + } +} diff --git a/plugin/src/main/resources/META-INF/plugin.xml b/plugin/src/main/resources/META-INF/plugin.xml index c2f39a6b1..32f82d791 100644 --- a/plugin/src/main/resources/META-INF/plugin.xml +++ b/plugin/src/main/resources/META-INF/plugin.xml @@ -59,7 +59,7 @@ implementationClass="ch.kleis.lcaac.plugin.language.ide.insight.LcaAssignmentAnnotator"/> + implementationClass="ch.kleis.lcaac.plugin.language.psi.manipulators.PsiDataRefManipulator"/> + + + Date: Sun, 28 Jan 2024 00:20:17 +0100 Subject: [PATCH 14/24] psi lca type checker --- plugin/build.gradle.kts | 19 ++- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 5 +- .../ch/kleis/lcaac/plugin/language/Lca.flex | 1 + .../ide/syntax/LcaSyntaxHighlighter.kt | 2 +- .../psi/mixin/PsiBlockForEachMixin.kt | 2 +- .../psi/mixin/PsiColumnDefinitionMixin.kt | 2 +- .../type_checker/PsiLcaTypeChecker.kt | 34 ++++ .../psi/reference/DataSourceReferenceTest.kt | 8 +- .../type_checker/PsiLcaTypeCheckerTest.kt | 154 ++++++++++++++++++ 9 files changed, 210 insertions(+), 17 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 48f2cd293..ca00caf0f 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -28,14 +28,15 @@ kotlin { // Configure project's dependencies repositories { mavenCentral() - maven { - name = "github" - url = uri("https://maven.pkg.github.com/kleis-technology/lcaac") - credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") - } - } +// maven { +// name = "github" +// url = uri("https://maven.pkg.github.com/kleis-technology/lcaac") +// credentials { +// username = System.getenv("GITHUB_ACTOR") +// password = System.getenv("GITHUB_TOKEN") +// } +// } + mavenLocal() } sourceSets { @@ -47,7 +48,7 @@ sourceSets { } dependencies { - implementation("ch.kleis.lcaac:core:1.5.0") + implementation("ch.kleis.lcaac:core:1.6.0") implementation(files(layout.buildDirectory.dir("stdlib/ef3.1")) { builtBy("generateEmissionFactors31") diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index 042a09cd0..caa4e3ca5 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -57,6 +57,7 @@ FOR_EACH_KEYWORD = 'for_each' SUM_KEYWORD = 'sum' LOOKUP_KEYWORD = 'lookup' + DEFAULT_RECORD_KEYWORD = 'default_record' NUMBER = 'number' LSQBRACE = '[' @@ -244,7 +245,7 @@ params ::= "params" "{" assignment* "}" variables ::= "variables" "{" assignment* "}" -assignment ::= dataRef (('=' dataExpression) | ('from' dataSourceRef)){ +assignment ::= dataRef '=' dataExpression{ implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiAssignment"] mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiAssignmentMixin" } @@ -328,7 +329,7 @@ parenQuantityExpression ::= "(" dataExpression ")" { extends=dataExpression } scaleQuantityExpression ::= NUMBER dataExpression { extends=dataExpression methods=[scale="NUMBER"]} stringExpression ::= STRING_LITERAL { extends=dataExpression } sliceExpression ::= dataRef '.' columnRef { extends=dataExpression } -recordExpression ::= 'lookup' dataSourceExpression { extends=dataExpression } +recordExpression ::= ('default_record' 'from' | 'lookup') dataSourceExpression { extends=dataExpression } colExpression ::= 'sum' '(' dataSourceExpression ',' columnRef ('*' columnRef)* ')' { extends=dataExpression } /* diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex index 2aad14f26..9c54d7e1d 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.flex @@ -104,6 +104,7 @@ CommentContent = .* "for_each" { return LcaTypes.FOR_EACH_KEYWORD; } "sum" { return LcaTypes.SUM_KEYWORD; } "lookup" { return LcaTypes.LOOKUP_KEYWORD; } + "default_record" { return LcaTypes.DEFAULT_RECORD_KEYWORD; } [-]?{Number_Int} ("." {Number_Int}? )? {Number_Exp}? { return LcaTypes.NUMBER; } {Identifier} { return LcaTypes.IDENTIFIER; } diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt index 20ea04b7b..007d2e009 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LcaSyntaxHighlighter.kt @@ -56,7 +56,7 @@ class LcaSyntaxHighlighter : SyntaxHighlighterBase() { REFERENCE_UNIT_KEYWORD, SYMBOL_KEYWORD, NAME_KEYWORD, TYPE_KEYWORD, COMPARTMENT_KEYWORD, SUB_COMPARTMENT_KEYWORD, - LOCATION_KEYWORD, SUM_KEYWORD, LOOKUP_KEYWORD -> FIELD_KEYS + LOCATION_KEYWORD, SUM_KEYWORD, LOOKUP_KEYWORD, DEFAULT_RECORD_KEYWORD -> FIELD_KEYS TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt index fe7fe1f04..7b1be9bcf 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiBlockForEachMixin.kt @@ -15,7 +15,7 @@ abstract class PsiBlockForEachMixin(node: ASTNode) : ASTWrapperPsiElement(node), } override fun getValue(): LcaDataSourceExpression { - return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataSourceExpression::class.java).elementAt(1) + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataSourceExpression::class.java).elementAt(0) } override fun getName(): String { diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt index 3b920fb9f..a99a08326 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/psi/mixin/PsiColumnDefinitionMixin.kt @@ -14,7 +14,7 @@ abstract class PsiColumnDefinitionMixin(node: ASTNode) : ASTWrapperPsiElement(no } override fun getValue(): LcaDataExpression { - return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataExpression::class.java).elementAt(1) + return PsiTreeUtil.getChildrenOfTypeAsList(this, LcaDataExpression::class.java).elementAt(0) } override fun getName(): String { diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt index 70c37caa5..805102167 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt @@ -138,8 +138,10 @@ class PsiLcaTypeChecker { is LcaStringExpression -> TString is LcaScaleQuantityExpression -> element.dataExpression?.let { checkDataExpression(it) } ?: throw PsiTypeCheckException("missing expression") + is LcaParenQuantityExpression -> element.dataExpression?.let { checkDataExpression(it) } ?: throw PsiTypeCheckException("missing expression") + is LcaExponentialQuantityExpression -> { val exponent = element.exponent.text.toDouble() val tyBase = checkDataExpression(element.dataExpression, TQuantity::class.java) @@ -164,10 +166,42 @@ class PsiLcaTypeChecker { } } + is LcaColExpression -> { + val columns = columnsOf(element.dataSourceExpression.dataSourceRef) + val requestedColumns = element.columnRefList + val unknownColumns = requestedColumns + .filter { !columns.containsKey(it.name) } + if (unknownColumns.isNotEmpty()) + throw PsiTypeCheckException("columns $unknownColumns not found in schema of '${element.dataSourceExpression.dataSourceRef.name}'") + return columns.values + .map { checkDataExpression(it, TQuantity::class.java) } + .reduce { acc, e -> TQuantity(acc.dimension.multiply(e.dimension)) } + } + + is LcaRecordExpression -> { + val columns = columnsOf(element.dataSourceExpression.dataSourceRef) + return TRecord(columns.mapValues { checkDataExpression(it.value) }) + } + + is LcaSliceExpression -> { + val columnDefinition = element.columnRef.reference.resolve() as LcaColumnDefinition? + ?: throw PsiTypeCheckException("unknown column '${element.columnRef.name}'") + checkDataExpression(columnDefinition.getValue()) + } else -> throw PsiTypeCheckException("Unknown expression $element") } } + private fun columnsOf(e: LcaDataSourceRef): Map { + val ds = e.reference.resolve() as LcaDataSourceDefinition? + ?: throw PsiTypeCheckException("unknown data source '${e.name}'") + val schema = ds.schemaDefinitionList + .firstOrNull() + ?: throw PsiTypeCheckException("missing schema in '${ds.name}'") + return schema.columnDefinitionList + .associate { it.name to it.dataExpression } + } + private fun checkDataRef(element: PsiDataRef): TypeDataExpression { return rec.guard { el: PsiDataRef -> el.reference.resolve() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt index 81bb2e176..e214a0d6c 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt @@ -2,6 +2,7 @@ package ch.kleis.lcaac.plugin.language.psi.reference import ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStubKeyIndex import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex +import ch.kleis.lcaac.plugin.psi.LcaRecordExpression import com.intellij.testFramework.fixtures.BasePlatformTestCase import org.junit.Test import org.junit.runner.RunWith @@ -29,19 +30,20 @@ class DataSourceReferenceTest: BasePlatformTestCase() { process p { params { - row from inventory + row = default_record from inventory } } """.trimIndent()) val dataSource = DataSourceStubKeyIndex.findDataSources( project, "$pkgName.inventory" ).first() - val ref = ProcessStubKeyIndex.findProcesses( + val recordExpression = ProcessStubKeyIndex.findProcesses( project, "$pkgName.p" ).first() .paramsList.first() .assignmentList.first() - .dataSourceRef!! + .dataExpressionList.first() as LcaRecordExpression + val ref = recordExpression.dataSourceExpression.dataSourceRef // when val actual = ref.reference.resolve() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt index aebf4110b..dabc5560a 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt @@ -21,6 +21,160 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { return "" } + @Test + fun test_sliceExpression() { + // given + val pkgName = {}.javaClass.enclosingMethod.name + myFixture.createFile( + "$pkgName.lca", """ + package $pkgName + + datasource source { + location = "source.csv" + schema { + mass = 1 km + dt = 1 hour + } + } + + variables { + row = default_record from source + x = row.mass + } + """.trimIndent() + ) + val target = GlobalAssigmentStubKeyIndex.findGlobalAssignments( + project, + "$pkgName.x" + ).first() + .dataExpressionList[1] + val checker = PsiLcaTypeChecker() + + // when + val actual = checker.check(target) + + // then + val expected = TQuantity(DimensionFixture.length) + assertEquals(expected, actual) + } + + @Test + fun test_defaultRecordFrom() { + // given + val pkgName = {}.javaClass.enclosingMethod.name + myFixture.createFile( + "$pkgName.lca", """ + package $pkgName + + datasource source { + location = "source.csv" + schema { + geo = "GLO" + mass = 1 kg + } + } + + process p { + params { + x = default_record from source + } + } + """.trimIndent() + ) + val target = ProcessStubKeyIndex.findProcesses( + project, + "$pkgName.p" + ).first() + .paramsList.first() + .assignmentList.first() + val checker = PsiLcaTypeChecker() + + // when + val actual = checker.check(target) + + // then + val expected = TRecord(mapOf( + "geo" to TString, + "mass" to TQuantity(DimensionFixture.mass) + )) + assertEquals(expected, actual) + } + + @Test + fun test_whenLookup() { + // given + val pkgName = {}.javaClass.enclosingMethod.name + myFixture.createFile( + "$pkgName.lca", """ + package $pkgName + + datasource source { + location = "source.csv" + schema { + geo = "GLO" + mass = 1 kg + } + } + + variables { + x = lookup source + } + """.trimIndent() + ) + val target = GlobalAssigmentStubKeyIndex.findGlobalAssignments( + project, + "$pkgName.x" + ).first() + .dataExpressionList[1] + val checker = PsiLcaTypeChecker() + + // when + val actual = checker.check(target) + + // then + val expected = TRecord(mapOf( + "geo" to TString, + "mass" to TQuantity(DimensionFixture.mass) + )) + assertEquals(expected, actual) + } + + @Test + fun test_whenSum() { + // given + val pkgName = {}.javaClass.enclosingMethod.name + myFixture.createFile( + "$pkgName.lca", """ + package $pkgName + + datasource source { + location = "source.csv" + schema { + mass = 1 km + dt = 1 hour + } + } + + variables { + x = sum(source, mass * dt) + } + """.trimIndent() + ) + val target = GlobalAssigmentStubKeyIndex.findGlobalAssignments( + project, + "$pkgName.x" + ).first() + .dataExpressionList[1] + val checker = PsiLcaTypeChecker() + + // when + val actual = checker.check(target) + + // then + val expected = TQuantity(DimensionFixture.length.multiply(DimensionFixture.time)) + assertEquals(expected, actual) + } + @Test fun test_whenScaleExpression_missingInnerExpression() { // given From bdd84eda8c49dbefa2ff2a35e3093cac7ea81db4 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 00:37:48 +0100 Subject: [PATCH 15/24] fix bnf data expression order --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 19 +++++++++++-------- .../psi/reference/DataSourceReferenceTest.kt | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index caa4e3ca5..575af0ff6 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -275,7 +275,7 @@ technoProductExchange ::= dataExpression outputProductSpec technoInputExchange ::= terminalTechnoInputExchange | technoBlockForEach terminalTechnoInputExchange ::= dataExpression inputProductSpec -technoBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | technoInputExchange)* '}' { +technoBlockForEach ::= 'for_each' dataRef 'from' dataSourceExpression '{' (variables | technoInputExchange)* '}' { implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach"] mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiBlockForEachMixin" } @@ -283,7 +283,7 @@ technoBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | bioExchange ::= terminalBioExchange | bioBlockForEach terminalBioExchange ::= dataExpression substanceSpec -bioBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | bioExchange)* '}' { +bioBlockForEach ::= 'for_each' dataRef 'from' dataSourceExpression '{' (variables | bioExchange)* '}' { implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach"] mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiBlockForEachMixin" } @@ -291,7 +291,7 @@ bioBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | bio impactExchange ::= terminalImpactExchange | impactBlockForEach terminalImpactExchange ::= dataExpression indicatorRef -impactBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | impactExchange)* '}' { +impactBlockForEach ::= 'for_each' dataRef 'from' dataSourceExpression '{' (variables | impactExchange)* '}' { implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach"] mixin="ch.kleis.lcaac.plugin.language.psi.mixin.PsiBlockForEachMixin" } @@ -301,16 +301,19 @@ impactBlockForEach ::= 'for_each' dataRef 'from' dataSourceRef '{' (variables | Use GrammarKit's expression-related syntax and rules to generate a Pratt parser. */ -dataExpression ::= exponentialQuantityExpression - | mulGroup +dataExpression ::= mulGroup | addGroup + | exponentialQuantityExpression | baseGroup - | recordExpression - | colExpression private addGroup ::= addQuantityExpression | subQuantityExpression private mulGroup ::= scaleQuantityExpression | mulQuantityExpression | divQuantityExpression -private baseGroup ::= parenQuantityExpression | stringExpression | colExpression | sliceExpression | dataRef +private baseGroup ::= parenQuantityExpression + | stringExpression + | recordExpression + | colExpression + | sliceExpression + | dataRef fake binaryOperatorExpression ::= dataExpression dataExpression { extends=dataExpression diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt index e214a0d6c..ddcc6e5af 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/psi/reference/DataSourceReferenceTest.kt @@ -24,7 +24,7 @@ class DataSourceReferenceTest: BasePlatformTestCase() { datasource inventory { location = "inventory.csv" schema { - "mass" = 1 kg + mass = 1 kg } } @@ -42,7 +42,7 @@ class DataSourceReferenceTest: BasePlatformTestCase() { ).first() .paramsList.first() .assignmentList.first() - .dataExpressionList.first() as LcaRecordExpression + .getValue() as LcaRecordExpression val ref = recordExpression.dataSourceExpression.dataSourceRef // when From 3f88a14f9825eb85f9956d702d8dc43606e42d4d Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 00:59:30 +0100 Subject: [PATCH 16/24] renaming + fix type checker --- ...=> LcaTerminalTechnoInputExchangeAnnotator.kt} | 2 +- .../language/type_checker/PsiLcaTypeChecker.kt | 11 ++++++++++- plugin/src/main/resources/META-INF/plugin.xml | 2 +- ...caTerminalTechnoInputExchangeAnnotatorTest.kt} | 15 +++++++-------- 4 files changed, 19 insertions(+), 11 deletions(-) rename plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/{LcaTechnoInputExchangeAnnotator.kt => LcaTerminalTechnoInputExchangeAnnotator.kt} (97%) rename plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/{LcaTechnoInputExchangeAnnotatorTest.kt => LcaTerminalTechnoInputExchangeAnnotatorTest.kt} (93%) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTerminalTechnoInputExchangeAnnotator.kt similarity index 97% rename from plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt rename to plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTerminalTechnoInputExchangeAnnotator.kt index e5ed24705..cd59a882b 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotator.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTerminalTechnoInputExchangeAnnotator.kt @@ -13,7 +13,7 @@ import com.intellij.lang.annotation.AnnotationHolder import com.intellij.lang.annotation.Annotator import com.intellij.psi.PsiElement -class LcaTechnoInputExchangeAnnotator : Annotator { +class LcaTerminalTechnoInputExchangeAnnotator : Annotator { override fun annotate(element: PsiElement, holder: AnnotationHolder) { if (element !is LcaTerminalTechnoInputExchange) { return diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt index 805102167..d8ead4397 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt @@ -2,6 +2,7 @@ package ch.kleis.lcaac.plugin.language.type_checker import ch.kleis.lcaac.core.lang.dimension.Dimension import ch.kleis.lcaac.core.lang.type.* +import ch.kleis.lcaac.plugin.language.psi.type.PsiBlockForEach import ch.kleis.lcaac.plugin.language.psi.type.PsiProcess import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiDataRef import ch.kleis.lcaac.plugin.language.psi.type.unit.UnitDefinitionType @@ -21,6 +22,13 @@ class PsiLcaTypeChecker { is LcaTerminalTechnoInputExchange -> checkTerminalTechnoInputExchange(element) is LcaTechnoProductExchange -> checkTechnoProductExchange(element) is LcaTerminalBioExchange -> checkTerminalBioExchange(element) + + // the following checks the type of the data source expression in the block for each + is PsiBlockForEach -> { + val columns = columnsOf(element.getValue().dataSourceRef) + return TRecord(columns.mapValues { checkDataExpression(it.value) }) + } + else -> throw PsiTypeCheckException("Uncheckable type: $element") } } @@ -210,7 +218,8 @@ class PsiLcaTypeChecker { is TQuantity -> ty is TUnit -> TQuantity(ty.dimension) is TString -> ty - else -> throw PsiTypeCheckException("expected TQuantity, TUnit or TString, found $ty") + is TRecord -> ty + else -> throw PsiTypeCheckException("expected TQuantity, TUnit, TString or TRecord, found $ty") } } ?: throw PsiTypeCheckException("unbound reference ${el.name}") diff --git a/plugin/src/main/resources/META-INF/plugin.xml b/plugin/src/main/resources/META-INF/plugin.xml index 32f82d791..25f017614 100644 --- a/plugin/src/main/resources/META-INF/plugin.xml +++ b/plugin/src/main/resources/META-INF/plugin.xml @@ -44,7 +44,7 @@ + implementationClass="ch.kleis.lcaac.plugin.language.ide.insight.LcaTerminalTechnoInputExchangeAnnotator"/> diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTerminalTechnoInputExchangeAnnotatorTest.kt similarity index 93% rename from plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt rename to plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTerminalTechnoInputExchangeAnnotatorTest.kt index 3336ea45c..1ffe1e6a4 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTechnoInputExchangeAnnotatorTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/insight/LcaTerminalTechnoInputExchangeAnnotatorTest.kt @@ -1,7 +1,6 @@ package ch.kleis.lcaac.plugin.language.ide.insight import ch.kleis.lcaac.plugin.language.psi.stub.process.ProcessStubKeyIndex -import ch.kleis.lcaac.plugin.psi.LcaTerminalTechnoInputExchange import com.intellij.codeInspection.ProblemHighlightType import com.intellij.lang.annotation.HighlightSeverity import com.intellij.testFramework.fixtures.BasePlatformTestCase @@ -12,7 +11,7 @@ import org.junit.runners.JUnit4 @Suppress("DialogTitleCapitalization") @RunWith(JUnit4::class) -class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { +class LcaTerminalTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { override fun getTestDataPath(): String { return "testdata" @@ -36,7 +35,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() - val annotator = LcaTechnoInputExchangeAnnotator() + val annotator = LcaTerminalTechnoInputExchangeAnnotator() // when @@ -79,7 +78,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() - val annotator = LcaTechnoInputExchangeAnnotator() + val annotator = LcaTerminalTechnoInputExchangeAnnotator() // when @@ -116,7 +115,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() - val annotator = LcaTechnoInputExchangeAnnotator() + val annotator = LcaTerminalTechnoInputExchangeAnnotator() // when @@ -156,7 +155,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() - val annotator = LcaTechnoInputExchangeAnnotator() + val annotator = LcaTerminalTechnoInputExchangeAnnotator() // when @@ -201,7 +200,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() .getInputs().first().terminalTechnoInputExchange!! val mock = AnnotationHolderMock() - val annotator = LcaTechnoInputExchangeAnnotator() + val annotator = LcaTerminalTechnoInputExchangeAnnotator() // when @@ -237,7 +236,7 @@ class LcaTechnoInputExchangeAnnotatorTest : BasePlatformTestCase() { val element = ProcessStubKeyIndex.findProcesses(project, "$pkgName.p").first() .getInputs().first() val mock = AnnotationHolderMock() - val annotator = LcaTechnoInputExchangeAnnotator() + val annotator = LcaTerminalTechnoInputExchangeAnnotator() // when annotator.annotate(element, mock.holder) From 1a30af586f0c293b2eeeb1a863351198d0812fe0 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 09:57:37 +0100 Subject: [PATCH 17/24] formatting --- .../ide/style/LcaFormattingModelBuilder.kt | 11 +++ .../language/ide/style/LcaIndentBlock.kt | 1 + .../language/ide/style/LcaIndentBlockTest.kt | 86 +++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaFormattingModelBuilder.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaFormattingModelBuilder.kt index 22d291c7d..34ce06740 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaFormattingModelBuilder.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaFormattingModelBuilder.kt @@ -85,6 +85,11 @@ class LcaFormattingModelBuilder : FormattingModelBuilder { .spacing(0, 0, 0, true, 1) .beforeInside(ASSERT, TEST) .spacing(0, 0, 0, true, 1) + // Datasource + .around(DATA_SOURCE_REF).spaces(1) + // Block for each + .around(MATCH_KEYWORD).spaces(1) + .around(FOR_EACH_KEYWORD).spaces(1) // Comments .before(COMMENT_CONTENT) .spaces(0) @@ -109,6 +114,12 @@ class LcaFormattingModelBuilder : FormattingModelBuilder { .spaces(1) .before(SUBSTANCE_SPEC) .spaces(1) + .before(SUM_KEYWORD).spaces(1) + .after(SUM_KEYWORD).spaces(0) + .around(LOOKUP_KEYWORD).spaces(1) + .around(DEFAULT_RECORD_KEYWORD).spaces(1) + .before(COMMA).spaces(0) + .after(COMMA).spaces(1) // Substances .before(INDICATOR_REF) .spaces(1) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlock.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlock.kt index f85dc0c31..5ede0fe5d 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlock.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlock.kt @@ -31,6 +31,7 @@ class LcaIndentBlock(node: ASTNode, private val spaceBuilder: SpacingBuilder) : META_ASSIGNMENT, ALIAS_FOR_FIELD, COMMENT_LINE, COMMENT_BLOCK_START, COMMENT_CONTENT, COMMENT_BLOCK_END, ASSERT, GIVEN, RANGE_ASSERTION, + SCHEMA_DEFINITION, COLUMN_DEFINITION, LOCATION_FIELD, -> Indent.getNormalIndent(true) else -> Indent.getNoneIndent() diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt index b09c56766..daa11db42 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt @@ -7,6 +7,92 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class LcaIndentBlockTest : FormatterTestCase() { + @Test + fun test_columnAndRecordExpressions() { + doTextTest( + """ + variables { + a = sum ( source , mass * n_items) + b = default_record from source + c = lookup source match geo = "GLO" + d = c.mass * b.n_items + } + """.trimIndent(), + """ + variables { + a = sum( source, mass * n_items ) + b = default_record from source + c = lookup source match geo = "GLO" + d = c.mass * b.n_items + } + """.trimIndent(), + ) + } + @Test + fun test_formattingBlockForEach() { + doTextTest( + """ + process p { + inputs { + for_each row from source { + 1 kg wheat + } + } + emissions { + for_each row from source match geo = "GLO" { + 2 kg wheat + } + } + impacts { + for_each row from source match (id = "abc-01", geo = "GLO") { + 3 kg wheat + } + } + } + """.trimIndent(), + """ + process p { + inputs { + for_each row from source { + 1 kg wheat + } + } + emissions { + for_each row from source match geo = "GLO" { + 2 kg wheat + } + } + impacts { + for_each row from source match ( id = "abc-01", geo = "GLO" ) { + 3 kg wheat + } + } + } + """.trimIndent() + ) + } + @Test + fun test_formattingDataSource() { + doTextTest( + """ + datasource source { + location = "source.csv" + schema { + mass = 1 kg + } + } + """.trimIndent(), + """ + datasource source { + location = "source.csv" + schema { + mass = 1 kg + } + } + """.trimIndent() + ) + } + @Test fun test_formattingTest() { doTextTest( From d5afa7fb0317ba8c174df7c1dc73b33d5e4ba609 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 11:13:28 +0100 Subject: [PATCH 18/24] lca mapper --- .../ch/kleis/lcaac/plugin/language/Lca.bnf | 6 +- .../lcaac/plugin/language/loader/LcaLoader.kt | 16 +- .../lcaac/plugin/language/loader/LcaMapper.kt | 127 ++++++++-- .../plugin/language/loader/LcaLoaderTest.kt | 234 ++++++++++++++++++ 4 files changed, 355 insertions(+), 28 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf index 575af0ff6..e745c1d73 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/Lca.bnf @@ -114,7 +114,7 @@ dataSourceDefinition ::= 'datasource' dataSourceRef '{' (locationField | schemaD elementTypeClass="ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStubElementType" stubClass = "ch.kleis.lcaac.plugin.language.psi.stub.datasource.DataSourceStub" } -locationField ::= 'location' '=' STRING_LITERAL +locationField ::= 'location' '=' STRING_LITERAL { methods=[value="STRING_LITERAL"] } schemaDefinition ::= 'schema' '{' columnDefinition* '}' columnDefinition ::= columnRef '=' dataExpression { implements=["ch.kleis.lcaac.plugin.language.psi.type.PsiColumnDefinition"] @@ -332,7 +332,9 @@ parenQuantityExpression ::= "(" dataExpression ")" { extends=dataExpression } scaleQuantityExpression ::= NUMBER dataExpression { extends=dataExpression methods=[scale="NUMBER"]} stringExpression ::= STRING_LITERAL { extends=dataExpression } sliceExpression ::= dataRef '.' columnRef { extends=dataExpression } -recordExpression ::= ('default_record' 'from' | 'lookup') dataSourceExpression { extends=dataExpression } +recordExpression ::= (opDefaultRecord | opLookup) dataSourceExpression { extends=dataExpression } +opDefaultRecord ::= 'default_record' 'from' +opLookup ::= 'lookup' colExpression ::= 'sum' '(' dataSourceExpression ',' columnRef ('*' columnRef)* ')' { extends=dataExpression } /* diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt index d00643a28..144c3a560 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt @@ -4,6 +4,7 @@ import ch.kleis.lcaac.core.lang.* import ch.kleis.lcaac.core.lang.dimension.Dimension import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException import ch.kleis.lcaac.core.lang.expression.DataExpression +import ch.kleis.lcaac.core.lang.expression.EDataSource import ch.kleis.lcaac.core.lang.expression.EProcessTemplate import ch.kleis.lcaac.core.lang.expression.ESubstanceCharacterization import ch.kleis.lcaac.core.lang.register.* @@ -22,6 +23,7 @@ class LcaLoader( val unitDefinitions = files.flatMap { it.getUnitDefinitions() } val processDefinitions = files.flatMap { it.getProcesses() } val substanceDefinitions = files.flatMap { it.getSubstances() } + val dataSourceDefinitions = files.flatMap { it.getDataSourceDefinitions() } val dimensions: DimensionRegister = try { DimensionRegister.empty() @@ -48,7 +50,7 @@ class LcaLoader( throw EvaluatorException("Duplicate substance ${e.duplicates} defined") } - val globals= try { + val globals = try { DataRegister.empty>() .plus( unitDefinitions @@ -72,6 +74,17 @@ class LcaLoader( throw EvaluatorException("Duplicate global variable ${e.duplicates} defined") } + val dataSources = try { + + DataSourceRegister.empty>() + .plus( + dataSourceDefinitions.map { DataSourceKey(it.getDataSourceRef().name) to dataSourceDefinition(it) } + .asIterable() + ) + } catch (e: RegisterException) { + throw EvaluatorException("Duplicate data source ${e.duplicates} defined") + } + val processTemplates = try { ProcessTemplateRegister.empty>() .plus( @@ -85,6 +98,7 @@ class LcaLoader( return SymbolTable( data = globals, + dataSources = dataSources, processTemplates = processTemplates, dimensions = dimensions, substanceCharacterizations = substanceCharacterizations, diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt index 026157fd8..a425cb9ab 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt @@ -13,6 +13,7 @@ import ch.kleis.lcaac.core.math.QuantityOperations import ch.kleis.lcaac.plugin.language.psi.type.PsiProcess import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiIndicatorRef import ch.kleis.lcaac.plugin.psi.* +import com.intellij.psi.util.PsiTreeUtil class LcaMapper( private val ops: QuantityOperations @@ -117,15 +118,28 @@ class LcaMapper( ) - private fun impact(exchange: LcaImpactExchange): ImpactBlock { - return exchange.terminalImpactExchange?.let { - EImpactBlockEntry( - EImpact( - dataExpression(it.dataExpression), - indicatorSpec(it.indicatorRef), + private fun impact(ctx: LcaImpactExchange): ImpactBlock { + return when { + ctx.terminalImpactExchange != null -> { + EImpactBlockEntry( + EImpact( + dataExpression(ctx.terminalImpactExchange!!.dataExpression), + indicatorSpec(ctx.terminalImpactExchange!!.indicatorRef), + ) ) - ) - } ?: EImpactBlockForEach("", EDataSourceRef(""), emptyMap(), emptyList()) + } + ctx.impactBlockForEach != null -> { + val rowRef = ctx.impactBlockForEach!!.getDataRef().name + val dataSourceExpression = dataSourceExpression(ctx.impactBlockForEach!!.getValue()) + val locals = ctx.impactBlockForEach!!.getVariablesList() + .flatMap { it.assignmentList } + .associate { it.getDataRef().name to dataExpression(it.getValue()) } + val entries = ctx.impactBlockForEach!!.impactExchangeList + .map { impact(it) } + EImpactBlockForEach(rowRef, dataSourceExpression, locals, entries) + } + else -> throw EvaluatorException("invalid impact exchange") + } } private fun indicatorSpec(variable: PsiIndicatorRef): EIndicatorSpec { @@ -134,15 +148,40 @@ class LcaMapper( ) } - fun technoInputExchange(psiExchange: LcaTechnoInputExchange): TechnoBlock { - return psiExchange.terminalTechnoInputExchange?.let { - ETechnoBlockEntry( - ETechnoExchange( - dataExpression(it.dataExpression), - inputProductSpec(it.inputProductSpec), + fun technoInputExchange(ctx: LcaTechnoInputExchange): TechnoBlock { + return when { + ctx.terminalTechnoInputExchange != null -> + ETechnoBlockEntry( + ETechnoExchange( + dataExpression(ctx.terminalTechnoInputExchange!!.dataExpression), + inputProductSpec(ctx.terminalTechnoInputExchange!!.inputProductSpec), + ) ) - ) - } ?: ETechnoBlockForEach("", EDataSourceRef(""), emptyMap(), emptyList()) + + ctx.technoBlockForEach != null -> { + val rowRef = ctx.technoBlockForEach!!.getDataRef().name + val dataSourceExpression = dataSourceExpression(ctx.technoBlockForEach!!.getValue()) + val locals = ctx.technoBlockForEach!!.getVariablesList() + .flatMap { it.assignmentList } + .associate { it.getDataRef().name to dataExpression(it.getValue()) } + val entries = ctx.technoBlockForEach!!.technoInputExchangeList + .map { technoInputExchange(it) } + ETechnoBlockForEach(rowRef, dataSourceExpression, locals, entries) + } + + else -> throw EvaluatorException("invalid techno input exchange") + } + } + + private fun dataSourceExpression(ctx: LcaDataSourceExpression): DataSourceExpression { + val ref = ctx.dataSourceRef.name + val rowSelectors = ctx.rowFilter + ?.rowSelectorList + ?: emptyList() + val filter = rowSelectors + .associate { it.columnRef.name to dataExpression(it.dataExpression) } + return if (filter.isEmpty()) EDataSourceRef(ref) + else EFilter(EDataSourceRef(ref), filter) } private fun outputProductSpec( @@ -198,16 +237,41 @@ class LcaMapper( return dataExpression(element.dataExpression) } - private fun bioExchange(psiExchange: LcaBioExchange, symbolTable: SymbolTable): BioBlock { - return psiExchange.terminalBioExchange?.let { - val quantity = dataExpression(it.dataExpression) - EBioBlockEntry( - EBioExchange( - quantity, - substanceSpec(it.substanceSpec, quantity, symbolTable) + private fun bioExchange(ctx: LcaBioExchange, symbolTable: SymbolTable): BioBlock { + return when { + ctx.terminalBioExchange != null -> { + val quantity = dataExpression(ctx.terminalBioExchange!!.dataExpression) + EBioBlockEntry( + EBioExchange( + quantity, + substanceSpec(ctx.terminalBioExchange!!.substanceSpec, quantity, symbolTable) + ) ) - ) - } ?: EBioBlockForEach("", EDataSourceRef(""), emptyMap(), emptyList()) + } + ctx.bioBlockForEach != null -> { + val rowRef = ctx.bioBlockForEach!!.getDataRef().name + val dataSourceExpression = dataSourceExpression(ctx.bioBlockForEach!!.getValue()) + val locals = ctx.bioBlockForEach!!.getVariablesList() + .flatMap { it.assignmentList } + .associate { it.getDataRef().name to dataExpression(it.getValue()) } + val entries = ctx.bioBlockForEach!!.bioExchangeList + .map { bioExchange(it, symbolTable) } + EBioBlockForEach(rowRef, dataSourceExpression, locals, entries) + } + else -> throw EvaluatorException("invalid bio exchange") + } + } + + fun dataSourceDefinition(ctx: LcaDataSourceDefinition): EDataSource { + val location = ctx.locationFieldList.firstOrNull()?.value?.text?.trim('"') + ?: throw EvaluatorException("missing location field") + val schema = ctx.schemaDefinitionList.firstOrNull() + ?.columnDefinitionList?.associate { it.getColumnRef().name to dataExpression(it.getValue()) } + ?: throw EvaluatorException("missing schema") + return EDataSource( + location, + schema, + ) } fun dataExpression(dataExpression: LcaDataExpression): DataExpression { @@ -248,6 +312,19 @@ class LcaMapper( } is LcaStringExpression -> EStringLiteral(dataExpression.text.trim('"')) + + is LcaSliceExpression -> { + val record = dataExpression(dataExpression.dataRef) + val index = dataExpression.columnRef.name + ERecordEntry(record, index) + } + + is LcaRecordExpression -> { + val dataSource = dataSourceExpression(dataExpression.dataSourceExpression) + return dataExpression.opDefaultRecord?.let { EDefaultRecordOf(dataSource) } + ?: dataExpression.opLookup?.let { EFirstRecordOf(dataSource) } + ?: throw EvaluatorException("Unknown record expression: $dataExpression ") + } else -> throw EvaluatorException("Unknown data expression: $dataExpression") } } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt index 7d38532c5..02588ff25 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt @@ -21,6 +21,240 @@ import kotlin.test.assertFailsWith class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { private val ops = BasicOperations + @Test + fun test_dataSourceRelatedDataExpressions() { + // given + val file = parseFile( + "hello", """ + variables { + a = lookup source + b = lookup source match geo = "GLO" + c = default_record from source + d = a.quantity + } + """.trimIndent() + ) as LcaFile + val parser = LcaLoader( + sequenceOf(file), + ops, + ) + + // when + val symbolTable = parser.load() + val actual = listOf("a", "b", "c", "d") + .associateWith { symbolTable.getData(it)!! } + + // then + val expected: Map> = mapOf( + "a" to EFirstRecordOf(EDataSourceRef("source")), + "b" to EFirstRecordOf(EFilter(EDataSourceRef("source"), mapOf("geo" to EStringLiteral("GLO")))), + "c" to EDefaultRecordOf(EDataSourceRef("source")), + "d" to ERecordEntry(EDataRef("a"), "quantity"), + ) + assertEquals(expected, actual) + } + + @Test + fun test_impactBlockForEach() { + // given + val file = parseFile( + "hello", """ + process p { + impacts { + for_each row from source match id = "abc" { + row.quantity wheat + } + } + } + """.trimIndent() + ) as LcaFile + val parser = LcaLoader( + sequenceOf(file), + ops, + ) + + // when + val actual = parser.load().getTemplate("p") + + // then + val expected = EProcessTemplate( + emptyMap(), + emptyMap(), + EProcess( + "p", + impacts = listOf( + EImpactBlockForEach( + "row", + EFilter( + EDataSourceRef("source"), + mapOf("id" to EStringLiteral("abc"))), + emptyMap(), + listOf( + EImpactBlockEntry( + EImpact( + ERecordEntry( + EDataRef("row"), + "quantity", + ), + EIndicatorSpec("wheat") + ) + ) + ), + ) + ) + ) + ) + assertEquals(expected, actual) + } + + @Test + fun test_bioBlockForEach() { + // given + val file = parseFile( + "hello", """ + process p { + emissions { + for_each row from source match id = "abc" { + row.quantity wheat + } + } + } + """.trimIndent() + ) as LcaFile + val parser = LcaLoader( + sequenceOf(file), + ops, + ) + + // when + val actual = parser.load().getTemplate("p") + + // then + val expected = EProcessTemplate( + emptyMap(), + emptyMap(), + EProcess( + "p", + biosphere = listOf( + EBioBlockForEach( + "row", + EFilter( + EDataSourceRef("source"), + mapOf("id" to EStringLiteral("abc"))), + emptyMap(), + listOf( + EBioBlockEntry( + EBioExchange( + ERecordEntry( + EDataRef("row"), + "quantity", + ), + ESubstanceSpec( + "wheat", + type = SubstanceType.EMISSION, + referenceUnit = EUnitOf( + EQuantityClosure( + SymbolTable.empty(), + ERecordEntry(EDataRef("row"), "quantity") + ) + ) + ) + ) + ) + ), + ) + ) + ) + ) + assertEquals(expected, actual) + } + + @Test + fun test_technoBlockForEach() { + // given + val file = parseFile( + "hello", """ + process p { + inputs { + for_each row from source match id = "abc" { + row.quantity wheat + } + } + } + """.trimIndent() + ) as LcaFile + val parser = LcaLoader( + sequenceOf(file), + ops, + ) + + // when + val actual = parser.load().getTemplate("p") + + // then + val expected = EProcessTemplate( + emptyMap(), + emptyMap(), + EProcess( + "p", + inputs = listOf( + ETechnoBlockForEach( + "row", + EFilter( + EDataSourceRef("source"), + mapOf("id" to EStringLiteral("abc"))), + emptyMap(), + listOf( + ETechnoBlockEntry( + ETechnoExchange( + ERecordEntry( + EDataRef("row"), + "quantity", + ), + EProductSpec("wheat") + ) + ) + ), + ) + ) + ) + ) + assertEquals(expected, actual) + } + + @Test + fun test_dataSourceDefinition() { + // given + val file = parseFile( + "hello", """ + datasource source { + location = "source.csv" + schema { + geo = "GLO" + mass = 1 kg + } + } + """.trimIndent() + ) as LcaFile + val parser = LcaLoader( + sequenceOf(file), + ops, + ) + + // when + val actual = parser.load().getDataSource("source") + + // then + val expected = EDataSource( + "source.csv", + mapOf( + "geo" to EStringLiteral("GLO"), + "mass" to EQuantityScale(BasicNumber(1.0), EDataRef("kg")) + ) + ) + assertEquals(expected, actual) + } + @Test fun test_stringVariables() { // given From e37284e91c07c3075224d5f1260a2769f610372b Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 11:29:22 +0100 Subject: [PATCH 19/24] fix file collector --- .../ch/kleis/lcaac/plugin/language/loader/LcaFileCollector.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaFileCollector.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaFileCollector.kt index f0c535095..8c34c7709 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaFileCollector.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaFileCollector.kt @@ -1,7 +1,9 @@ package ch.kleis.lcaac.plugin.language.loader import ch.kleis.lcaac.plugin.language.psi.LcaFile +import ch.kleis.lcaac.plugin.psi.LcaColumnRef import ch.kleis.lcaac.plugin.psi.LcaDataRef +import ch.kleis.lcaac.plugin.psi.LcaDataSourceRef import ch.kleis.lcaac.plugin.psi.LcaInputProductSpec import ch.kleis.lcaac.plugin.psi.LcaProcessTemplateSpec import ch.kleis.lcaac.plugin.psi.LcaSubstanceSpec @@ -63,6 +65,8 @@ class LcaFileCollector( file, LcaSubstanceSpec::class.java, LcaDataRef::class.java, + LcaDataSourceRef::class.java, + LcaColumnRef::class.java, LcaInputProductSpec::class.java, LcaProcessTemplateSpec::class.java, ).asSequence() From 4e5e6b185bd0fa74e0082db6175926d1c2a177fe Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 11:31:28 +0100 Subject: [PATCH 20/24] mapper: column expression --- .../lcaac/plugin/language/loader/LcaMapper.kt | 8 ++++++++ .../language/ide/style/LcaIndentBlockTest.kt | 3 ++- .../plugin/language/loader/LcaLoaderTest.kt | 16 ++++++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt index a425cb9ab..dd945e5a6 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt @@ -325,6 +325,14 @@ class LcaMapper( ?: dataExpression.opLookup?.let { EFirstRecordOf(dataSource) } ?: throw EvaluatorException("Unknown record expression: $dataExpression ") } + + is LcaColExpression -> { + val dataSource = dataSourceExpression(dataExpression.dataSourceExpression) + val columns = dataExpression.columnRefList + .map { it.name } + ESumProduct(dataSource, columns) + } + else -> throw EvaluatorException("Unknown data expression: $dataExpression") } } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt index daa11db42..45b7666d8 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/style/LcaIndentBlockTest.kt @@ -14,7 +14,7 @@ class LcaIndentBlockTest : FormatterTestCase() { variables { a = sum ( source , mass * n_items) b = default_record from source - c = lookup source match geo = "GLO" + c = lookup source match geo = "GLO" d = c.mass * b.n_items } """.trimIndent(), @@ -28,6 +28,7 @@ class LcaIndentBlockTest : FormatterTestCase() { """.trimIndent(), ) } + @Test fun test_formattingBlockForEach() { doTextTest( diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt index 02588ff25..fe9abcb4c 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoaderTest.kt @@ -31,6 +31,7 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { b = lookup source match geo = "GLO" c = default_record from source d = a.quantity + e = sum( source match geo = "GLO", n_items * mass ) } """.trimIndent() ) as LcaFile @@ -41,7 +42,7 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { // when val symbolTable = parser.load() - val actual = listOf("a", "b", "c", "d") + val actual = listOf("a", "b", "c", "d", "e") .associateWith { symbolTable.getData(it)!! } // then @@ -50,6 +51,10 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { "b" to EFirstRecordOf(EFilter(EDataSourceRef("source"), mapOf("geo" to EStringLiteral("GLO")))), "c" to EDefaultRecordOf(EDataSourceRef("source")), "d" to ERecordEntry(EDataRef("a"), "quantity"), + "e" to ESumProduct( + EFilter(EDataSourceRef("source"), mapOf("geo" to EStringLiteral("GLO"))), + listOf("n_items", "mass") + ) ) assertEquals(expected, actual) } @@ -87,7 +92,8 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { "row", EFilter( EDataSourceRef("source"), - mapOf("id" to EStringLiteral("abc"))), + mapOf("id" to EStringLiteral("abc")) + ), emptyMap(), listOf( EImpactBlockEntry( @@ -140,7 +146,8 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { "row", EFilter( EDataSourceRef("source"), - mapOf("id" to EStringLiteral("abc"))), + mapOf("id" to EStringLiteral("abc")) + ), emptyMap(), listOf( EBioBlockEntry( @@ -202,7 +209,8 @@ class LcaLoaderTest : ParsingTestCase("", "lca", LcaParserDefinition()) { "row", EFilter( EDataSourceRef("source"), - mapOf("id" to EStringLiteral("abc"))), + mapOf("id" to EStringLiteral("abc")) + ), emptyMap(), listOf( ETechnoBlockEntry( From 555977fe157b5597bc9454629efedcd5e440dc40 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 12:00:27 +0100 Subject: [PATCH 21/24] core upgrade 1.6.0 --- plugin/build.gradle.kts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index ca00caf0f..97ab0a203 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -28,15 +28,14 @@ kotlin { // Configure project's dependencies repositories { mavenCentral() -// maven { -// name = "github" -// url = uri("https://maven.pkg.github.com/kleis-technology/lcaac") -// credentials { -// username = System.getenv("GITHUB_ACTOR") -// password = System.getenv("GITHUB_TOKEN") -// } -// } - mavenLocal() + maven { + name = "github" + url = uri("https://maven.pkg.github.com/kleis-technology/lcaac") + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } } sourceSets { From 767689df1ba5bce86c863b39023fa4795b84540f Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 12:20:30 +0100 Subject: [PATCH 22/24] completion keywords --- .../lcaac/plugin/language/ide/syntax/LanguageCompletion.kt | 5 ++++- .../plugin/language/ide/syntax/LanguageCompletionTest.kt | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletion.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletion.kt index de1108de8..751f2eb1d 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletion.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletion.kt @@ -45,7 +45,10 @@ class LanguageCompletion : CompletionContributor() { "reference_unit", "symbol", "dimension", "alias_for", // Unit block "variables", "params", "labels", // Process Block "products", "inputs", "resources", "emissions", "land_use", "impacts", // Process SubBlocks - "test", "given", "assert", "between", "and" // Test blocks + "test", "given", "assert", "between", "and", // Test blocks + "datasource", "schema", "location", // Data source blocks + "for_each", // For each + "sum", "lookup", "default_record" // Primitives ) private val listOfKeywordPattern = Regex("(LcaTokenType.*) expected, got") private val keywordsPattern = Regex("LcaTokenType\\.([^ ,]*)(, | or |)") diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletionTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletionTest.kt index a301e5993..bf507e878 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletionTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/ide/syntax/LanguageCompletionTest.kt @@ -27,7 +27,8 @@ class LanguageCompletionTest : LcaCompletionTestCase() { "substance", "unit", "variables", - "test" + "test", + "datasource" ) } From ab12414d7c1e0305e47e5795cdf8a1ecab1527e1 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 16:23:36 +0100 Subject: [PATCH 23/24] loader: data sources for closure --- .../ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt | 2 +- .../ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt index 144c3a560..d18329206 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaLoader.kt @@ -89,7 +89,7 @@ class LcaLoader( ProcessTemplateRegister.empty>() .plus( processDefinitions - .map { Pair(it.buildUniqueKey(), process(it, globals)) } + .map { Pair(it.buildUniqueKey(), process(it, globals, dataSources)) } .asIterable() ) } catch (e: RegisterException) { diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt index dd945e5a6..a3f334c55 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/loader/LcaMapper.kt @@ -5,10 +5,7 @@ import ch.kleis.lcaac.core.lang.dimension.Dimension import ch.kleis.lcaac.core.lang.dimension.UnitSymbol import ch.kleis.lcaac.core.lang.evaluator.EvaluatorException import ch.kleis.lcaac.core.lang.expression.* -import ch.kleis.lcaac.core.lang.register.DataKey -import ch.kleis.lcaac.core.lang.register.DataRegister -import ch.kleis.lcaac.core.lang.register.Register -import ch.kleis.lcaac.core.lang.register.RegisterException +import ch.kleis.lcaac.core.lang.register.* import ch.kleis.lcaac.core.math.QuantityOperations import ch.kleis.lcaac.plugin.language.psi.type.PsiProcess import ch.kleis.lcaac.plugin.language.psi.type.ref.PsiIndicatorRef @@ -36,6 +33,7 @@ class LcaMapper( fun process( psiProcess: LcaProcess, globals: DataRegister, + dataSources: DataSourceRegister, ): EProcessTemplate { val name = psiProcess.name val labels = psiProcess.getLabels().mapValues { EStringLiteral(it.value) } @@ -51,6 +49,7 @@ class LcaMapper( } catch (e: RegisterException) { throw EvaluatorException("Conflict between local variable(s) ${e.duplicates} and a global definition.") }, + dataSources = dataSources ) val products = generateTechnoProductExchanges(psiProcess, symbolTable) val inputs = psiProcess.getInputs().map { technoInputExchange(it) } From 24729cb6c80fd5e8a60437283cd173aec23885e4 Mon Sep 17 00:00:00 2001 From: Peva Blanchard Date: Sun, 28 Jan 2024 16:40:01 +0100 Subject: [PATCH 24/24] fix type checker --- .../plugin/language/type_checker/PsiLcaTypeChecker.kt | 7 +++++-- .../plugin/language/type_checker/PsiLcaTypeCheckerTest.kt | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt index d8ead4397..11991e429 100644 --- a/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt +++ b/plugin/src/main/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeChecker.kt @@ -177,11 +177,14 @@ class PsiLcaTypeChecker { is LcaColExpression -> { val columns = columnsOf(element.dataSourceExpression.dataSourceRef) val requestedColumns = element.columnRefList + .map { it.name } val unknownColumns = requestedColumns - .filter { !columns.containsKey(it.name) } + .filter { !columns.containsKey(it) } if (unknownColumns.isNotEmpty()) throw PsiTypeCheckException("columns $unknownColumns not found in schema of '${element.dataSourceExpression.dataSourceRef.name}'") - return columns.values + return columns + .filterKeys { requestedColumns.contains(it) } + .values .map { checkDataExpression(it, TQuantity::class.java) } .reduce { acc, e -> TQuantity(acc.dimension.multiply(e.dimension)) } } diff --git a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt index dabc5560a..4dc6b3946 100644 --- a/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt +++ b/plugin/src/test/kotlin/ch/kleis/lcaac/plugin/language/type_checker/PsiLcaTypeCheckerTest.kt @@ -152,6 +152,8 @@ class PsiLcaTypeCheckerTest : BasePlatformTestCase() { schema { mass = 1 km dt = 1 hour + geo = "GLO" + n_items = 1 p } }