diff --git a/src/main/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilter.groovy b/src/main/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilter.groovy new file mode 100644 index 0000000..a0ee3f1 --- /dev/null +++ b/src/main/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilter.groovy @@ -0,0 +1,38 @@ +package com.codebrig.arthur.observe.structure.filter.operator.misc + +import com.codebrig.arthur.SourceNode +import com.codebrig.arthur.observe.structure.StructureFilter +import com.codebrig.arthur.observe.structure.filter.InternalRoleFilter +import com.codebrig.arthur.observe.structure.filter.MultiFilter +import com.codebrig.arthur.observe.structure.filter.RoleFilter + +/** + * Match by Elvis operator + * + * @version 0.4 + * @since 0.4 + * @author Val Pecaoco + */ +class ElvisOperatorFilter extends StructureFilter { + + private final MultiFilter filter + + ElvisOperatorFilter() { + filter = MultiFilter.matchAll( + new RoleFilter("IF"), new RoleFilter("EXPRESSION"), new RoleFilter("RIGHT") + ) + } + + @Override + boolean evaluate(SourceNode node) { + boolean result = filter.evaluate(node) + if (result) { + def matched = MultiFilter.matchAll( + new RoleFilter("THEN"), + new InternalRoleFilter("if") + ).getFilteredNodes(node.children) + return !matched.hasNext() + } + return result + } +} diff --git a/src/test/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilterTest.groovy b/src/test/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilterTest.groovy new file mode 100644 index 0000000..83e7e3b --- /dev/null +++ b/src/test/groovy/com/codebrig/arthur/observe/structure/filter/operator/misc/ElvisOperatorFilterTest.groovy @@ -0,0 +1,41 @@ +package com.codebrig.arthur.observe.structure.filter.operator.misc + +import com.codebrig.arthur.ArthurTest +import com.codebrig.arthur.SourceLanguage +import com.codebrig.arthur.observe.structure.filter.FunctionFilter +import com.codebrig.arthur.observe.structure.filter.MultiFilter +import com.codebrig.arthur.observe.structure.filter.NameFilter +import gopkg.in.bblfsh.sdk.v1.protocol.generated.Encoding +import org.junit.Test + +import static org.junit.Assert.* + +class ElvisOperatorFilterTest extends ArthurTest { + + @Test + void elvisOperator_Php() { + assertElvisOperatorPresent(new File("src/test/resources/same/operators/Operators.php")) + } + + private static void assertElvisOperatorPresent(File file) { + assertElvisOperatorPresent(file, "") + } + + private static void assertElvisOperatorPresent(File file, String qualifiedName) { + def language = SourceLanguage.getSourceLanguage(file) + def resp = client.parse(file.name, file.text, language.key, Encoding.UTF8$.MODULE$) + + def foundElvisOperator = false + def functionFilter = new FunctionFilter() + def nameFilter = new NameFilter("elvisOperator") + MultiFilter.matchAll(functionFilter, nameFilter).getFilteredNodes(language, resp.uast).each { + assertEquals(qualifiedName + "elvisOperator()", it.name) + + new ElvisOperatorFilter().getFilteredNodes(it).each { + assertFalse(foundElvisOperator) + foundElvisOperator = true + } + } + assertTrue(foundElvisOperator) + } +} diff --git a/src/test/resources/same/operators/Operators.php b/src/test/resources/same/operators/Operators.php index f267052..948b576 100644 --- a/src/test/resources/same/operators/Operators.php +++ b/src/test/resources/same/operators/Operators.php @@ -48,4 +48,10 @@ function ternaryOperator() $b = ($a == 1) ? 20 : 30; } +function elvisOperator() +{ + $a = 20; + $b = $a ?: 30; +} + ?> \ No newline at end of file