From 338832808daacfee8c83471604c4086714168e36 Mon Sep 17 00:00:00 2001 From: Philippe Kernevez Date: Tue, 22 Aug 2023 17:22:58 +0200 Subject: [PATCH] Code simplification and bug fixes --- .../ch/kleis/lcaplugin/language/Lca.bnf | 6 +- .../language/ide/syntax/LanguageCompletion.kt | 58 +++++++------- .../ide/syntax/LanguageCompletionTest.kt | 75 +++++++++++++++++++ 3 files changed, 107 insertions(+), 32 deletions(-) diff --git a/src/main/kotlin/ch/kleis/lcaplugin/language/Lca.bnf b/src/main/kotlin/ch/kleis/lcaplugin/language/Lca.bnf index 63f619de5..360b870f9 100644 --- a/src/main/kotlin/ch/kleis/lcaplugin/language/Lca.bnf +++ b/src/main/kotlin/ch/kleis/lcaplugin/language/Lca.bnf @@ -22,7 +22,7 @@ TYPE_RESOURCE_KEYWORD = 'Resource' TYPE_LAND_USE_KEYWORD = 'Land_use' COMPARTMENT_KEYWORD = 'compartment' - SUB_COMPARTMENT_KEYWORD = 'sub-compartment' + SUB_COMPARTMENT_KEYWORD = 'sub_compartment' IMPACTS_KEYWORD = 'impacts' META_KEYWORD = "meta" FROM_KEYWORD = "from" @@ -31,12 +31,12 @@ INDICATOR_KEYWORD = 'indicator' VARIABLES_KEYWORD = 'variables' UNIT_KEYWORD = 'unit' - REFERENCE_UNIT_KEYWORD = 'reference-unit' + REFERENCE_UNIT_KEYWORD = 'reference_unit' ALIAS_FOR_KEYWORD = 'alias_for' ALLOCATE_KEYWORD = 'allocate' NAME_KEYWORD = 'name' DIMENSION_KEYWORD = 'dimension' - PARAMETERS_KEYWORD = 'parameters' + PARAMETERS_KEYWORD = 'params' INPUTS_KEYWORD = 'inputs' EMISSIONS_KEYWORD = 'emissions' RESOURCES_KEYWORD = 'resources' diff --git a/src/main/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletion.kt b/src/main/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletion.kt index 1020bdb34..b47aef719 100644 --- a/src/main/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletion.kt +++ b/src/main/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletion.kt @@ -1,8 +1,5 @@ package ch.kleis.lcaplugin.language.ide.syntax -import ch.kleis.lcaplugin.ide.template.ErrorHelper.Companion.containsAllErrors -import ch.kleis.lcaplugin.ide.template.ErrorHelper.Companion.isInErrorInRootBlock -import ch.kleis.lcaplugin.ide.template.ErrorHelper.Companion.isInErrorInSubBlock import com.intellij.codeInsight.completion.CompletionContributor import com.intellij.codeInsight.completion.CompletionParameters import com.intellij.codeInsight.completion.CompletionResultSet @@ -10,45 +7,48 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.psi.PsiErrorElement -private val ALL_MANDATORY_SUB_BLOCK_KEYWORD = listOf( - "name", "type", "compartment", "sub_compartment", "reference_unit", // Substance - "symbol" // Unit -) - class LanguageCompletion : CompletionContributor() { override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) { super.fillCompletionVariants(parameters, result) - if (isInErrorInRootBlock(parameters.position)) { // Root Block - result.addElements("package", "import", "process", "variables", "substance", "unit") - } else if (isInErrorInSubBlock(parameters.position)) { // Substance or Unit block + if (parameters.position.parent is PsiErrorElement) { val parent = parameters.position.parent as PsiErrorElement - val expected = findExpectedToken(parent) - if (expected != null && expected in ALL_MANDATORY_SUB_BLOCK_KEYWORD) { - result.addElements(expected) - } else if (containsAllErrors(parent, "impacts", "meta")) { // Substance optional blocks - result.addElements("impacts", "meta") - } else if (containsAllErrors(parent, "Emission", "Resource", "Land_use")) { // Substance.type - result.addElements("Emission", "Resource", "Land_use") - } else if (containsAllErrors(parent, "dimension", "alias_for")) { // Unit exclusive alternatives - result.addElements("dimension", "alias_for") - } else { - // Nothing to complete - } - } else { - // Nothing to complete + result.addElements(*extractKeyWordFromError(parent).toTypedArray()) } } - private val expectedPattern = Regex("LcaTokenType\\.(.*) expected, got") - private fun findExpectedToken(elt: PsiErrorElement): String? { - val grp = expectedPattern.find(elt.errorDescription)?.groupValues - return if (grp?.size == 2) grp[1] else null + private fun extractKeyWordFromError(elt: PsiErrorElement): List { + val grp = listOfKeywordPattern.find(elt.errorDescription)?.groupValues + return if (grp?.size == 2) { + val errors = grp[1] + keywordsPattern.findAll(errors) + .map { it.groupValues } + .filter { it.size >= 2 } + .map { it[1] } + .filter { it in keywordWhiteList } + .toList() + } else { + listOf() + } } + private val keywordWhiteList = + hashSetOf( + "meta", // All Blocks + "unit", "process", "substance", "import", "package", "variables", // Root + "name", "type", "compartment", "sub_compartment", "reference_unit", "impacts", // Substance block + "Emission", "Resource", "Land_use", // Substance types + "description", "author", "other", // Meta default keys + "reference_unit", "symbol", "dimension", "alias_for", // Unit block + "variables", "params", "labels", // Process Block + "products", "inputs", "resources", "emissions", "land_use", "impacts" // Process SubBlocks + ) + private val listOfKeywordPattern = Regex("(LcaTokenType.*) expected, got") + private val keywordsPattern = Regex("LcaTokenType\\.([^ ,]*)(, | or |)") + private fun CompletionResultSet.addElements(vararg strings: String) { strings.forEach { this.addElement(LookupElementBuilder.create(it)) } } diff --git a/src/test/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletionTest.kt b/src/test/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletionTest.kt index 7e3ba0110..44b0b530b 100644 --- a/src/test/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletionTest.kt +++ b/src/test/kotlin/ch/kleis/lcaplugin/language/ide/syntax/LanguageCompletionTest.kt @@ -174,6 +174,30 @@ substance mySubstance { } @Test + fun lookup_ShouldReturnMetaAndSubstance_ForSubstanceMetaBlock() { + // Given + fixture.configureByText( + "sampleShouldReturnEmpty_ForSubstanceMetaBlock.lca", """ +substance mySubstance { + name = "mySubstanceName" + type = Emission + compartment = "water" + sub_compartment = "sea water" + reference_unit = kg + +} +""" + ) + fixture.complete(CompletionType.BASIC) + + // When + val lookupElementStrings = fixture.lookupElementStrings + + // Then + assertNotNull(lookupElementStrings) + assertSameElements(lookupElementStrings!!, "meta", "impacts") + } + fun lookup_ShouldReturnEmpty_ForSubstanceMetaBlock() { // Given fixture.configureByText( @@ -220,6 +244,29 @@ substance mySubstance { assertSameElements(lookupElementStrings!!, "Emission", "Resource", "Land_use") } + @Test + fun lookup_ShouldReturnSubstanceSubCompartment_ForSubstance() { + // Given + fixture.configureByText( + "sampleShouldReturnEmpty_ForSubstanceMetaBlock.lca", """ +substance mySubstance { + name = "myname" + type = Emission + compartment = "water" + +} +""" + ) + fixture.complete(CompletionType.BASIC) + + // When + val lookupElementStrings = fixture.lookupElementStrings + + // Then + assertNotNull(lookupElementStrings) + assertSameElements(lookupElementStrings!!, "reference_unit", "sub_compartment") + } + @Test fun lookup_ShouldReturnEmpty_ForSubstanceImpactBlock() { // Given @@ -243,4 +290,32 @@ substance name { assertSameElements(lookupElementStrings!!) } + @Test + fun lookup_ShouldReturnProcess_ForProcess() { + // Given + fixture.configureByText( + "sampleShouldReturnEmpty_ForSubstanceImpactBlock.lca", """ +process p3 { + + + +} +""" + ) + fixture.complete(CompletionType.BASIC) + + // When + val lookupElementStrings = fixture.lookupElementStrings + + // Then + assertNotNull(lookupElementStrings) + assertSameElements( + lookupElementStrings!!, + "emissions", "impacts", "inputs", "labels", "land_use", "meta", "params", + "products", "resources", "variables", + + ) + } + + } \ No newline at end of file