[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[henshin-dev] Bug when using Attribute Conditions
|
Hey,
First thanks for creating this cool tool. It's a lot of fun working with
it. I found a bug while working with it though. Sometimes if you use
Attribute Conditions that use the modulo operation (%) the interpreter
fails with the exception that one of the attributes is unknwon.
After some research I found the problem in
org.eclipse.emf.henshin.interpreter.info.ConditionInfo. There the
condition is parsed and the code tries to extract all the used
parameters. I guess this is so that the conditions can be executed as
early as possible to prevent unused matching. The problem is that the
method extractParameter is not splitting the string correctly. It is
only splitting on some special characters not '%'. So when the js
expressiong variable%10==0; is parsed it results in the token
variable%10 which is not matching any of the defined parameters
(variable % 10 == 0; works though).
To prevent this from happening it would be better to use a regular
expression:
[$_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}][$_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}\\p{Mn}\\p{Mc}\\p{Nd}\\p{Pc}]+
(http://mathiasbynens.be/notes/javascript-identifiers)
This should match most possible javascript variable names (it does not
consider U+200C zero width non-joiner characters, U+200D zero width
joiner characters).
Here is the patch I would like to contribute to fix the bug.
Best regards,
Manuel Hegner
Index: plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/ConditionInfo.java
===================================================================
--- plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/ConditionInfo.java (revision 1989)
+++ plugins/org.eclipse.emf.henshin.interpreter/src/org/eclipse/emf/henshin/interpreter/info/ConditionInfo.java (working copy)
@@ -9,12 +9,13 @@
*/
package org.eclipse.emf.henshin.interpreter.info;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.emf.henshin.model.AttributeCondition;
import org.eclipse.emf.henshin.model.Parameter;
@@ -22,12 +23,14 @@
public class ConditionInfo {
+ private static final Pattern VALID_JS_VARIABLE_NAME=Pattern.compile("[$_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}][$_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}\\p{Mn}\\p{Mc}\\p{Nd}\\p{Pc}]+");
+
private Map<String, Collection<String>> conditionParameters;
public ConditionInfo(Rule rule) {
this.conditionParameters = new HashMap<String, Collection<String>>();
- Collection<String> parameterNames = new ArrayList<String>();
+ Collection<String> parameterNames = new HashSet<String>();
for (Parameter parameter : rule.getParameters()) {
parameterNames.add(parameter.getName());
}
@@ -41,17 +44,14 @@
private Collection<String> extractParameter(String testString, Collection<String> parameterNames) {
Collection<String> usedParameters = new HashSet<String>();
- StringTokenizer quoteParser = new StringTokenizer(testString, "\"\'");
+ StringTokenizer quoteParser = new StringTokenizer(testString, "\"\'"); //FIXME this can also lead to wrong results when escaped " or ' are used
while (quoteParser.hasMoreElements()) {
String nonQuotedString = quoteParser.nextToken();
- StringTokenizer variableParser = new StringTokenizer(nonQuotedString, ".,()\t\r\n<>=!+[] ");
- while (variableParser.hasMoreElements()) {
- String subString = variableParser.nextToken();
- for (String parameterName : parameterNames) {
- if (parameterName.equals(subString)) {
- usedParameters.add(parameterName);
- }
- }
+ Matcher m=VALID_JS_VARIABLE_NAME.matcher(nonQuotedString);
+ while(m.find()) {
+ String possibleVariableName=m.group();
+ if(parameterNames.contains(possibleVariableName))
+ usedParameters.add(possibleVariableName);
}
// discard the quoted part
if (quoteParser.hasMoreElements())