You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2022/12/23 16:11:58 UTC
[commons-jexl] branch JEXL-390 updated: JEXL-390: added pragma-anywhere feature that controls if pragmas can only be used before any statement;
This is an automated email from the ASF dual-hosted git repository.
henrib pushed a commit to branch JEXL-390
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git
The following commit(s) were added to refs/heads/JEXL-390 by this push:
new 0891da10 JEXL-390: added pragma-anywhere feature that controls if pragmas can only be used before any statement;
0891da10 is described below
commit 0891da10d235fd2320ee0cf450633f0b0c44145b
Author: henrib <he...@apache.org>
AuthorDate: Fri Dec 23 17:11:51 2022 +0100
JEXL-390: added pragma-anywhere feature that controls if pragmas can only be used before any statement;
---
.../org/apache/commons/jexl3/JexlFeatures.java | 39 ++++++++++++++++++++--
.../commons/jexl3/parser/FeatureController.java | 2 +-
.../apache/commons/jexl3/parser/JexlParser.java | 19 ++++++++---
.../org/apache/commons/jexl3/parser/Parser.jjt | 4 +--
.../org/apache/commons/jexl3/FeaturesTest.java | 8 +++++
5 files changed, 62 insertions(+), 10 deletions(-)
diff --git a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
index 35a80276..d8895add 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
@@ -41,8 +41,16 @@ import java.util.function.Predicate;
* <li>Method calls: calling methods (obj.method(...) or obj['method'](...)); when disabled, leaves function calls
* - including namespace prefixes - available
* <li>Structured literals: arrays, lists, maps, sets, ranges
- * <li>Pragmas: #pragma x y
+ * <li>Pragma: pragma construct as in <code>#pragma x y</code>
* <li>Annotation: @annotation statement;
+ * <li>Thin-arrow: use the thin-arrow, ie <code>-></code> for lambdas as in <code>x -> x + x</code>
+ * <li>Fat-arrow: use the fat-arrow, ie <code>=></code> for lambdas as in <code>x => x + x</code>
+ * <li>Namespace pragma: whether the <code>#pragma jexl.namespace.ns namespace</code> syntax is allowed</li>
+ * <li>Import pragma: whether the <code>#pragma jexl.import fully.qualified.class.name</code> syntax is allowed</li>
+ * <li>Comparator names: whether the comparator operator names can be used (as in <code>gt</code> for >,
+ * <code>lt</code> for <, ...)</li>
+ * <li>Pragma anywhere: whether pragma, that are <em>not</em> statements and handled before execution begins,
+ * can appear anywhere in the source or before any statements - ie at the beginning of a script.</li>
* </ul>
* @since 3.2
*/
@@ -60,7 +68,7 @@ public final class JexlFeatures {
"register", "reserved variable", "local variable", "assign/modify",
"global assign/modify", "array reference", "create instance", "loop", "function",
"method call", "set/map/array literal", "pragma", "annotation", "script", "lexical", "lexicalShade",
- "thin-arrow", "fat-arrow", "namespace pragma", "import pragma", "comparator names"
+ "thin-arrow", "fat-arrow", "namespace pragma", "import pragma", "comparator names", "pragma anywhere"
};
/** Registers feature ordinal. */
private static final int REGISTER = 0;
@@ -104,6 +112,8 @@ public final class JexlFeatures {
public static final int IMPORT_PRAGMA = 19;
/** Comparator names (legacy) syntax. */
public static final int COMPARATOR_NAMES = 20;
+ /** The pragma anywhere feature ordinal. */
+ public static final int PRAGMA_ANYWHERE = 21;
/**
* The default features flag mask.
*/
@@ -123,7 +133,8 @@ public final class JexlFeatures {
| (1L << THIN_ARROW)
| (1L << NS_PRAGMA)
| (1L << IMPORT_PRAGMA)
- | (1L << COMPARATOR_NAMES);
+ | (1L << COMPARATOR_NAMES)
+ | (1L << PRAGMA_ANYWHERE);
/**
* Creates an all-features-enabled instance.
@@ -543,6 +554,26 @@ public final class JexlFeatures {
return getFeature(PRAGMA);
}
+ /**
+ * Sets whether pragma constructs can appear anywhere in the code.
+ * <p>
+ * @param flag true to enable, false to disable
+ * @return this features instance
+ * @since 3.3
+ */
+ public JexlFeatures pragmaAnywhere(final boolean flag) {
+ setFeature(PRAGMA_ANYWHERE, flag);
+ return this;
+ }
+
+ /**
+ * @return true if pragma constructs can appear anywhere in the code, false otherwise
+ * @since 3.3
+ */
+ public boolean supportsPragmaAnywhere() {
+ return getFeature(PRAGMA_ANYWHERE);
+ }
+
/**
* Sets whether namespace pragma constructs are enabled.
* <p>
@@ -550,6 +581,7 @@ public final class JexlFeatures {
* (#pragma jexl.namespace....) will throw a parsing exception.
* @param flag true to enable, false to disable
* @return this features instance
+ * @since 3.3
*/
public JexlFeatures namespacePragma(final boolean flag) {
setFeature(NS_PRAGMA, flag);
@@ -558,6 +590,7 @@ public final class JexlFeatures {
/**
* @return true if namespace pragma are enabled, false otherwise
+ * @since 3.3
*/
public boolean supportsNamespacePragma() {
return getFeature(NS_PRAGMA);
diff --git a/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java b/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java
index e40d6ca9..dc11a22e 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/FeatureController.java
@@ -29,7 +29,7 @@ public class FeatureController extends ScriptVisitor {
private JexlFeatures features;
/**
- * Creates a features controller.
+ * Creates a feature controller.
*/
public FeatureController(final JexlFeatures features) {
this.features = features;
diff --git a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
index 56f65876..54141d18 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
@@ -201,6 +201,16 @@ public abstract class JexlParser extends StringParser {
return featureController.getFeatures();
}
+ /**
+ * Disables pragma feature is pragma-anywhere feature is disabled.
+ */
+ protected void controlPragmaAnywhere() {
+ JexlFeatures features = getFeatures();
+ if (features.supportsPragma() && !features.supportsPragmaAnywhere()) {
+ featureController.setFeatures(new JexlFeatures(featureController.getFeatures()).pragma(false));
+ }
+ }
+
/**
* Gets the frame used by this parser.
* <p> Since local variables create new symbols, it is important to
@@ -508,19 +518,20 @@ public abstract class JexlParser extends StringParser {
* @param value the pragma value
*/
protected void declarePragma(final String key, final Object value) {
- if (!getFeatures().supportsPragma()) {
+ JexlFeatures features = getFeatures();
+ if (!features.supportsPragma()) {
throwFeatureException(JexlFeatures.PRAGMA, getToken(0));
}
- if (PRAGMA_IMPORT.equals(key) && !getFeatures().supportsImportPragma()) {
+ if (PRAGMA_IMPORT.equals(key) && !features.supportsImportPragma()) {
throwFeatureException(JexlFeatures.IMPORT_PRAGMA, getToken(0));
}
if (pragmas == null) {
pragmas = new TreeMap<>();
}
// declaring a namespace
- Predicate<String> ns = getFeatures().namespaceTest();
+ Predicate<String> ns = features.namespaceTest();
if (ns != null && key.startsWith(PRAGMA_JEXLNS)) {
- if (!getFeatures().supportsNamespacePragma()) {
+ if (!features.supportsNamespacePragma()) {
throwFeatureException(JexlFeatures.NS_PRAGMA, getToken(0));
}
// jexl.namespace.***
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index cd6cc868..cb522f8a 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -324,7 +324,7 @@ ASTJexlScript JexlScript(Scope frame) : {
{
pushUnit(jjtThis);
}
- ( LOOKAHEAD(<PRAGMA>) Pragma() | Statement() )* <EOF>
+ ( LOOKAHEAD(<PRAGMA>) Pragma() | { controlPragmaAnywhere(); } Statement() )* <EOF>
{
popUnit(jjtThis);
return jjtThis.script();
@@ -338,7 +338,7 @@ ASTJexlScript JexlExpression(Scope frame) #JexlScript : {
{
pushUnit(jjtThis);
}
- ( Pragma() )* ( Expression() )? <EOF>
+ ( Pragma() )* { controlPragmaAnywhere(); } ( Expression() )? <EOF>
{
popUnit(jjtThis);
return jjtThis.script();
diff --git a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
index e635291f..300a4fad 100644
--- a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
+++ b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
@@ -267,6 +267,14 @@ public class FeaturesTest extends JexlTestCase {
};
checkFeature(f, scripts);
}
+ @Test
+ public void testPragmaAnywhere() throws Exception {
+ final JexlFeatures f = new JexlFeatures().pragmaAnywhere(false);
+ final String[] scripts = new String[]{
+ "var x = 3;\n#pragma foo 42",
+ };
+ checkFeature(f, scripts);
+ }
@Test
public void testMixedFeatures() throws Exception {