From 0207193b1b05006e1c3bf36772e43113ec21ee92 Mon Sep 17 00:00:00 2001 From: ahaase Date: Wed, 23 Jan 2008 23:47:27 +0000 Subject: strings returned by cached functions are now immutable to avoid accidental modifications of cached values --- .../eclipse/xtend/backend/FunctionInvokerImpl.java | 8 ++++++- .../xtend/backend/common/EfficientLazyString.java | 26 +++++++++++++++++++++- .../xtend/backend/expr/ConcatExpression.java | 6 ++--- .../java/EfficientLazyStringConverter.java | 4 +--- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/FunctionInvokerImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/FunctionInvokerImpl.java index 0a07a216..f1603c1a 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/FunctionInvokerImpl.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/FunctionInvokerImpl.java @@ -12,6 +12,7 @@ package org.eclipse.xtend.backend; import java.util.List; +import org.eclipse.xtend.backend.common.EfficientLazyString; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.FunctionInvoker; @@ -26,7 +27,12 @@ final class FunctionInvokerImpl implements FunctionInvoker { private final DoubleKeyCache , Object> _cache = new DoubleKeyCache, Object> () { @Override protected Object create (Function f, List params) { - return f.invoke (_ctx, params.toArray()); + final Object result = f.invoke (_ctx, params.toArray()); + + if (result instanceof EfficientLazyString) + ((EfficientLazyString) result).makeImmutable(); + + return result; } }; diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/EfficientLazyString.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/EfficientLazyString.java index 23fbcfc6..d8eb167b 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/EfficientLazyString.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/common/EfficientLazyString.java @@ -31,12 +31,27 @@ import java.util.List; */ public class EfficientLazyString implements CharSequence { private boolean _isDirty = false; + private boolean _isImmutable = false; private String _asString = ""; private final List _contents = new ArrayList(); private EfficientLazyString _parent = null; - public void append (Object o) { + + public static EfficientLazyString createAppendedString (EfficientLazyString s, Object o) { + if (s._isImmutable) { + final EfficientLazyString result = new EfficientLazyString (); + result.append (s); + result.append (o); + return result; + } + else { + s.append (o); + return s; + } + } + + private void append (Object o) { if (o != null) { setDirty(); _contents.add(o); @@ -46,6 +61,15 @@ public class EfficientLazyString implements CharSequence { } } + /** + * makes this EfficientLazyString immutable, forcing concatenation to create a new EfficientLazyString instance. This + * is done to comply with caching semantics, where the string value once returned from a function should not be + * modified implicitly from outside that function. + */ + public void makeImmutable () { + _isImmutable = true; + } + /** * if a hierarchy of EfficientLazyStrings was toString'ed, and later on of the parts down in * the tree becomes dirty again, all parents are dirty as well by implication. diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/ConcatExpression.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/ConcatExpression.java index 9b9dd8d9..c432c7b5 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/ConcatExpression.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/expr/ConcatExpression.java @@ -34,10 +34,10 @@ public final class ConcatExpression extends ExpressionBase { @Override protected Object evaluateInternal (ExecutionContext ctx) { - final EfficientLazyString result = new EfficientLazyString (); + EfficientLazyString result = new EfficientLazyString (); - for (ExpressionBase expr: _parts) - result.append (Helpers.overridableToString (ctx, expr.evaluate(ctx))); + for (ExpressionBase expr: _parts) + result = EfficientLazyString.createAppendedString (result, Helpers.overridableToString (ctx, expr.evaluate(ctx))); return result; } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/java/EfficientLazyStringConverter.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/java/EfficientLazyStringConverter.java index 10daf1a6..7d11185a 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/java/EfficientLazyStringConverter.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/java/EfficientLazyStringConverter.java @@ -14,9 +14,7 @@ class EfficientLazyStringConverter implements JavaBuiltinConverter { if (o == null) return null; - final EfficientLazyString result = new EfficientLazyString (); - result.append (o); - return result; + return EfficientLazyString.createAppendedString (new EfficientLazyString(), o); } public Object javaToBackend (Object o) { -- cgit v1.2.3