diff options
26 files changed, 355 insertions, 217 deletions
diff --git a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java index 40cddea5..651594dd 100644 --- a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java +++ b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/EnumType.java @@ -18,6 +18,7 @@ import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.StaticProperty; import org.eclipse.xtend.backend.types.AbstractProperty; import org.eclipse.xtend.backend.types.AbstractType; +import org.eclipse.xtend.backend.types.builtin.StringType; import org.eclipse.xtend.backend.types.emf.EObjectType; @@ -61,7 +62,7 @@ public final class EnumType extends AbstractType { final EObject obj = (EObject) o; return obj.eGet (obj.eClass ().getEStructuralFeature ("name")); } - }); + }, StringType.INSTANCE); } @Override diff --git a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java index 8d032517..42832f05 100644 --- a/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java +++ b/plugins/org.eclipse.xtend.backend.uml2types/src/org/eclipse/xtend/backend/types/uml2/internal/StereotypeType.java @@ -33,6 +33,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.types.AbstractProperty; import org.eclipse.xtend.backend.types.AbstractType; +import org.eclipse.xtend.backend.types.builtin.CollectionType; import org.eclipse.xtend.backend.types.uml2.UmlTypesystem; @@ -47,12 +48,12 @@ public final class StereotypeType extends AbstractType { super (name, name, superTypes (umlTs, stereoType).toArray (new BackendType[0])); //TODO uniqueRepresentation _stereoType = stereoType; - for (StereotypeProperty stp: getProperties(this, stereoType)) - register (stp); + for (StereotypeProperty stp: getProperties (this, stereoType, umlTs)) + register (stp, stp.getType()); } - private Collection<StereotypeProperty> getProperties (BackendType owningType, Stereotype stereoType) { + private Collection<StereotypeProperty> getProperties (BackendType owningType, Stereotype stereoType, UmlTypesystem umlTs) { final Collection<StereotypeProperty> result = new HashSet<StereotypeProperty> (); for (Property attrib: stereoType.getAttributes()) { @@ -67,8 +68,8 @@ public final class StereotypeType extends AbstractType { continue; } -// final BackendType backendType = (attrib.isMultivalued()) ? CollectionType.INSTANCE : umlTs.findType (umlType); - result.add (new StereotypeProperty (attrib.getName ())); + final BackendType backendType = (attrib.isMultivalued()) ? CollectionType.INSTANCE : umlTs.findType (umlType); + result.add (new StereotypeProperty (attrib.getName (), backendType)); } return result; @@ -132,8 +133,11 @@ public final class StereotypeType extends AbstractType { private final class StereotypeProperty extends AbstractProperty { - public StereotypeProperty (String name) { + private final BackendType _type; + + public StereotypeProperty (String name, BackendType type) { super (StereotypeType.this, Object.class, name, true, false); + _type = type; } @Override @@ -171,6 +175,10 @@ public final class StereotypeType extends AbstractType { throw new IllegalArgumentException("uml2 Element expected but was " + target.getClass().getName()); } + private BackendType getType () { + return _type; + } + private Object getDynamicValue(final Object value) { if (value instanceof EObject) { final EObject dynObject = (EObject) value; diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java index 6ae114e3..f1834e06 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/functions/internal/FunctionDefContextImpl.java @@ -96,10 +96,11 @@ public final class FunctionDefContextImpl implements FunctionDefContextInternal _publicFunctions.register (f); final NamedFunction old = _functions.get (f.getName(), f.getFunction().getParameterTypes().size()).register (f); + if (old != null && old.getFunction().getParameterTypes().size() > 0) _byFirstParameterType.get (old.getFunction().getParameterTypes().get (0)).remove (old); - - if (f.getFunction().getParameterTypes().size() > 0) + + if (f.getFunction().getParameterTypes().size() > 0) _byFirstParameterType.get (f.getFunction().getParameterTypes().get(0)).add (f); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java index f11aa4e4..8321c6ee 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/AbstractType.java @@ -21,13 +21,16 @@ import java.util.Map; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.ExpressionBase; import org.eclipse.xtend.backend.common.Function; +import org.eclipse.xtend.backend.common.FunctionDefContext; import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.common.Property; import org.eclipse.xtend.backend.common.StaticProperty; import org.eclipse.xtend.backend.types.builtin.ObjectType; import org.eclipse.xtend.backend.types.builtin.VoidType; import org.eclipse.xtend.backend.types.internal.SyntheticPropertyExtracter; +import org.eclipse.xtend.backend.util.StringHelper; /** @@ -65,12 +68,12 @@ public abstract class AbstractType implements BackendType { _superTypes = new ArrayList<BackendType> (superTypes); } - protected void register (Property p) { + protected void register (Property p, BackendType type) { _properties.put (p.getName(), p); -// register ("get" + StringHelper.firstUpper (p.getName()), new GetterOperation (p)); -// if (p.isWritable()) -// register ("set" + StringHelper.firstUpper (p.getName()), new SetterOperation (p)); + register ("get" + StringHelper.firstUpper (p.getName()), new GetterOperation (p)); + if (p.isWritable()) + register ("set" + StringHelper.firstUpper (p.getName()), new SetterOperation (p, type)); } protected void register (StaticProperty p) { @@ -118,7 +121,7 @@ public abstract class AbstractType implements BackendType { //this could be statically initialized in the constructor, but is intentionally done dynamically to prepare for // "dynamic properties" that are attached at runtime final Map<String, Property> result = new HashMap<String, Property> (); - + for (BackendType t: _superTypes) result.putAll (t.getProperties (ctx)); @@ -160,76 +163,83 @@ public abstract class AbstractType implements BackendType { //TODO synthetic setter operation --> middle end (requires knowledge of the property type!) -// private class SetterOperation implements Function { -// private final List<BackendType> _paramTypes = new ArrayList<BackendType> (); -// private final Property _property; -// -// public SetterOperation (Property property) { -// _property = property; -// -// _paramTypes.add (AbstractType.this); -// _paramTypes.add (property.getType ()); -// } -// -// public ExpressionBase getGuard () { -// return null; -// } -// -// public List<? extends BackendType> getParameterTypes () { -// return _paramTypes; -// } -// -// public Object invoke (ExecutionContext ctx, Object[] params) { -// _property.set (ctx, params[0], params[1]); -// return null; -// } -// -// public boolean isCached () { -// return false; -// } -// -// public FunctionDefContext getFunctionDefContext () { -// return null; -// } -// -// public void setFunctionDefContext (FunctionDefContext fdc) { -// throw new UnsupportedOperationException (); -// } -// } -// -// private class GetterOperation implements Function { -// private final List<BackendType> _paramTypes = new ArrayList<BackendType> (); -// private final Property _property; -// -// public GetterOperation (Property property) { -// _property = property; -// _paramTypes.add (AbstractType.this); -// } -// -// public ExpressionBase getGuard () { -// return null; -// } -// -// public List<? extends BackendType> getParameterTypes () { -// return _paramTypes; -// } -// -// public Object invoke (ExecutionContext ctx, Object[] params) { -// return _property.get (ctx, params[0]); -// } -// -// public boolean isCached () { -// return false; -// } -// -// public FunctionDefContext getFunctionDefContext () { -// return null; -// } -// -// public void setFunctionDefContext (FunctionDefContext fdc) { -// throw new UnsupportedOperationException (); -// } -// } + private class SetterOperation implements Function { + private final List<BackendType> _paramTypes = new ArrayList<BackendType> (); + private final Property _property; + + public SetterOperation (Property property, BackendType type) { + _property = property; + + _paramTypes.add (AbstractType.this); + _paramTypes.add (type); + } + + public ExpressionBase getGuard () { + return null; + } + + public List<? extends BackendType> getParameterTypes () { + return _paramTypes; + } + + public Object invoke (ExecutionContext ctx, Object[] params) { + _property.set (ctx, params[0], params[1]); + return null; + } + + public boolean isCached () { + return false; + } + + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } + } + + private class GetterOperation implements Function { + private final List<BackendType> _paramTypes = new ArrayList<BackendType> (); + private final Property _property; + + public GetterOperation (Property property) { + _property = property; + _paramTypes.add (AbstractType.this); + } + + public ExpressionBase getGuard () { + return null; + } + + public List<? extends BackendType> getParameterTypes () { + return _paramTypes; + } + + public Object invoke (ExecutionContext ctx, Object[] params) { + return _property.get (ctx, params[0]); + } + + public boolean isCached () { + return false; + } + + public FunctionDefContext getFunctionDefContext () { + return null; + } + + public void setFunctionDefContext (FunctionDefContext fdc) { + throw new UnsupportedOperationException (); + } + } + + + /** + * every type *must* implement a valid equals method, otherwise the backend will break! + */ + @Override + public abstract boolean equals (Object other); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/BooleanType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/BooleanType.java index cacc5284..21c97ee6 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/BooleanType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/BooleanType.java @@ -27,4 +27,9 @@ public final class BooleanType extends AbstractType { public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/CollectionType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/CollectionType.java index 5536bf7f..b15dbf5c 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/CollectionType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/CollectionType.java @@ -26,8 +26,13 @@ public final class CollectionType extends AbstractType { private CollectionType() { super ("Collection", "{builtin}Collection"); - register (new BuiltinProperty (this, "size", ReflectionHelper.getKnownMethod(Collection.class, "size"), null)); - register (new BuiltinProperty (this, "isEmpty", ReflectionHelper.getKnownMethod(Collection.class, "isEmpty"), null)); + register (new BuiltinProperty (this, "size", ReflectionHelper.getKnownMethod(Collection.class, "size"), null), LongType.INSTANCE); + register (new BuiltinProperty (this, "isEmpty", ReflectionHelper.getKnownMethod(Collection.class, "isEmpty"), null), BooleanType.INSTANCE); + } + + @Override + public boolean equals (Object other) { + return other == this; } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/DoubleType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/DoubleType.java index 05455c4e..3dbede2b 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/DoubleType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/DoubleType.java @@ -27,4 +27,9 @@ public final class DoubleType extends AbstractType { public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java index feccb871..6834a77c 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/FunctionType.java @@ -62,4 +62,9 @@ public final class FunctionType extends AbstractType { public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ListType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ListType.java index 96980df9..983bd3e8 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ListType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ListType.java @@ -28,4 +28,9 @@ public final class ListType extends AbstractType { public Object create() { return new ArrayList<Object>(); } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/LongType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/LongType.java index 7ea7459a..fc210370 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/LongType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/LongType.java @@ -27,4 +27,9 @@ public final class LongType extends AbstractType { public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/MapType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/MapType.java index e40cfbb2..a83bc822 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/MapType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/MapType.java @@ -25,8 +25,8 @@ public final class MapType extends AbstractType { private MapType () { super ("Map", "{builtin}Map"); - register (new BuiltinProperty (CollectionType.INSTANCE, "size", ReflectionHelper.getKnownMethod(Collection.class, "size"), null)); - register (new BuiltinProperty (CollectionType.INSTANCE, "isEmpty", ReflectionHelper.getKnownMethod(Collection.class, "isEmpty"), null)); + register (new BuiltinProperty (CollectionType.INSTANCE, "size", ReflectionHelper.getKnownMethod(Collection.class, "size"), null), LongType.INSTANCE); + register (new BuiltinProperty (CollectionType.INSTANCE, "isEmpty", ReflectionHelper.getKnownMethod(Collection.class, "isEmpty"), null), BooleanType.INSTANCE); } public static final MapType INSTANCE = new MapType (); @@ -35,4 +35,9 @@ public final class MapType extends AbstractType { public Object create() { return new HashMap <Object,Object> (); } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ObjectType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ObjectType.java index 9c72f887..933fc621 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ObjectType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/ObjectType.java @@ -55,11 +55,11 @@ public final class ObjectType implements BackendType { } public Object getProperty (ExecutionContext ctx, Object o, String name) { - throw new IllegalArgumentException ("ObjectType has no properties"); + return Collections.emptyList(); } public Map<String, ? extends StaticProperty> getStaticProperties () { - throw new IllegalArgumentException ("ObjectType has no static properties"); + return Collections.emptyMap(); } public Collection<? extends BackendType> getSuperTypes () { diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/PropertyType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/PropertyType.java index 40629918..346b130a 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/PropertyType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/PropertyType.java @@ -26,12 +26,17 @@ public final class PropertyType extends AbstractType { private PropertyType () { super ("Property", "{builtin}Property"); - register (new BuiltinProperty (this, "name", ReflectionHelper.getKnownMethod(Property.class, "getName"), null)); - register (new BuiltinProperty (this, "owner", ReflectionHelper.getKnownMethod(Property.class, "getOwner"), null)); + register (new BuiltinProperty (this, "name", ReflectionHelper.getKnownMethod(Property.class, "getName"), null), StringType.INSTANCE); + register (new BuiltinProperty (this, "owner", ReflectionHelper.getKnownMethod(Property.class, "getOwner"), null), TypeType.INSTANCE); } @Override public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/SetType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/SetType.java index ac340963..fc80352c 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/SetType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/SetType.java @@ -30,4 +30,9 @@ public final class SetType extends AbstractType { public Object create() { return new HashSet<Object>(); } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StaticPropertyType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StaticPropertyType.java index 3dda6411..578201f5 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StaticPropertyType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StaticPropertyType.java @@ -26,14 +26,19 @@ public final class StaticPropertyType extends AbstractType { private StaticPropertyType () { super ("StaticProperty", "{builtin}StaticProperty"); - register (new BuiltinProperty (this, "name", ReflectionHelper.getKnownMethod(Property.class, "getName"), null)); - register (new BuiltinProperty (this, "owner", ReflectionHelper.getKnownMethod(Property.class, "getOwner"), null)); + register (new BuiltinProperty (this, "name", ReflectionHelper.getKnownMethod(Property.class, "getName"), null), StringType.INSTANCE); + register (new BuiltinProperty (this, "owner", ReflectionHelper.getKnownMethod(Property.class, "getOwner"), null), TypeType.INSTANCE); } @Override public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StringType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StringType.java index 4ba664d0..650f4b29 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StringType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/StringType.java @@ -31,7 +31,7 @@ public final class StringType extends AbstractType { private StringType () { super ("String", "{builtin}String"); - register (new BuiltinProperty (this, "length", ReflectionHelper.getKnownMethod (CharSequence.class, "length"), null)); + register (new BuiltinProperty (this, "length", ReflectionHelper.getKnownMethod (CharSequence.class, "length"), null), LongType.INSTANCE); } @Override @@ -43,4 +43,9 @@ public final class StringType extends AbstractType { public Object create () { return ""; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java index a95d5df5..ebe849a9 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/TypeType.java @@ -35,9 +35,9 @@ public final class TypeType extends AbstractType { private TypeType () { super ("Type", "{builtin}Type"); - register (new BuiltinProperty (this, "name", ReflectionHelper.getKnownMethod (BackendType.class, "getName"), null)); - register (new BuiltinProperty (this, "superTypes", ReflectionHelper.getKnownMethod (BackendType.class, "getSuperTypes"), null)); - register (new BuiltinProperty (this, "allStaticProperties", ReflectionHelper.getKnownMethod (BackendType.class, "getStaticProperties"), null)); + register (new BuiltinProperty (this, "name", ReflectionHelper.getKnownMethod (BackendType.class, "getName"), null), StringType.INSTANCE); + register (new BuiltinProperty (this, "superTypes", ReflectionHelper.getKnownMethod (BackendType.class, "getSuperTypes"), null), CollectionType.INSTANCE); + register (new BuiltinProperty (this, "allStaticProperties", ReflectionHelper.getKnownMethod (BackendType.class, "getStaticProperties"), null), CollectionType.INSTANCE); register (new AbstractProperty (this, java.util.Map.class, "allProperties", true, false) { @@ -45,7 +45,7 @@ public final class TypeType extends AbstractType { protected Object getRaw (ExecutionContext ctx, Object o) { return ((BackendType) o).getProperties (ctx); } - }); + }, CollectionType.INSTANCE); register (new AbstractProperty (this, java.util.List.class, "allOperations", true, false) { @Override @@ -56,7 +56,7 @@ public final class TypeType extends AbstractType { result.addAll (t.getBuiltinOperations()); return result; } - }); + }, CollectionType.INSTANCE); register ("getProperty", new Function () { final List<? extends BackendType> _paramTypes = Arrays.asList (TypeType.this, StringType.INSTANCE); @@ -89,6 +89,11 @@ public final class TypeType extends AbstractType { } }); } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/VoidType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/VoidType.java index 6dc44122..3af53005 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/VoidType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/builtin/VoidType.java @@ -29,4 +29,9 @@ public final class VoidType extends AbstractType { public boolean isAssignableFrom (BackendType other) { return other == this; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/EObjectType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/EObjectType.java index 3a051e8d..8b5894a8 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/EObjectType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/EObjectType.java @@ -21,6 +21,7 @@ import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.types.AbstractProperty; import org.eclipse.xtend.backend.types.AbstractType; +import org.eclipse.xtend.backend.types.builtin.CollectionType; import org.eclipse.xtend.backend.types.builtin.VoidType; @@ -39,19 +40,19 @@ public final class EObjectType extends AbstractType { public Object getRaw (ExecutionContext ctx, Object o) { return ((EObject) o).eContainer(); } - }); + }, this); register (new AbstractProperty (INSTANCE, java.util.List.class, "eContents", true, false) { @Override public Object getRaw (ExecutionContext ctx, Object o) { return ((EObject) o).eContents(); } - }); + }, CollectionType.INSTANCE); register (new AbstractProperty (INSTANCE, EObject.class, "eRootContainer", true, false) { @Override public Object getRaw (ExecutionContext ctx, Object o) { return EcoreUtil.getRootContainer((EObject) o); } - }); + }, this); register (new AbstractProperty (INSTANCE, java.util.Set.class, "eAllContents", true, false) { @Override public Object getRaw (ExecutionContext ctx, Object o) { @@ -62,12 +63,17 @@ public final class EObjectType extends AbstractType { return result; } - }); + }, CollectionType.INSTANCE); } @Override public boolean isAssignableFrom (BackendType other) { return other == this || other == VoidType.INSTANCE; } + + @Override + public boolean equals (Object other) { + return other == this; + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java index 9be44328..9b68e7a8 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/emf/internal/EClassType.java @@ -52,13 +52,13 @@ public final class EClassType extends AbstractType { * operations that reference itself */ public void init (EmfTypesystem ts) { - initProperties (); + initProperties (ts); initOperations (ts); } - private void initProperties () { + private void initProperties (EmfTypesystem ts) { for (final EStructuralFeature feature: _cls.getEStructuralFeatures()) { -// final BackendType t = ts.getTypeForETypedElement(feature); + final BackendType t = ts.getTypeForETypedElement(feature); if (feature.isChangeable() && !feature.isUnsettable() && !feature.isDerived()) { register (new AbstractProperty (this, feature.getEType().getInstanceClass(), feature.getName(), true, true) { @@ -71,7 +71,7 @@ public final class EClassType extends AbstractType { public void setRaw (ExecutionContext ctx, Object o, Object newValue) { ((EObject) o).eSet(feature, newValue); } - }); + }, t); } else { register (new AbstractProperty (this, feature.getEType().getInstanceClass(), feature.getName(), true, false) { @@ -79,7 +79,7 @@ public final class EClassType extends AbstractType { public Object getRaw (ExecutionContext ctx, Object o) { return ((EObject) o).eGet(feature); } - }); + }, t); } } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/internal/SyntheticPropertyExtracter.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/internal/SyntheticPropertyExtracter.java index 99dededb..24b21c13 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/internal/SyntheticPropertyExtracter.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/internal/SyntheticPropertyExtracter.java @@ -52,7 +52,6 @@ public final class SyntheticPropertyExtracter { if (propAcc == null) continue; - final AccessorPair ap = _accessorPairs.get (refinePropertyName (propAcc.getSecond())); final boolean isSetter = propAcc.getFirst(); diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/AbstractJavaBeansTypesystem.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/AbstractJavaBeansTypesystem.java index a96717c1..344b3332 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/AbstractJavaBeansTypesystem.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/AbstractJavaBeansTypesystem.java @@ -10,7 +10,6 @@ Contributors: */ package org.eclipse.xtend.backend.types.java.internal; -import java.beans.IntrospectionException; import java.util.HashMap; import java.util.Map; @@ -45,22 +44,18 @@ public abstract class AbstractJavaBeansTypesystem implements BackendTypesystem { JavaBeansType result = _cache.get (cls); if (result != null) return result; - - result = new JavaBeansType (cls); + + result = new JavaBeansType (cls, this); _cache.put (cls, result); - try { - result.init (this); - } catch (IntrospectionException e) { - ErrorHandler.handle(e); - } + result.init (this); return result; } public BackendType findType (Object o) { if (o == null) return null; - + return findType (o.getClass()); } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaBeansType.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaBeansType.java index 71ed9eb1..04538ab5 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaBeansType.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/backend/types/java/internal/JavaBeansType.java @@ -10,27 +10,17 @@ Contributors: */ package org.eclipse.xtend.backend.types.java.internal; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; +import java.util.Arrays; import java.util.List; -import java.util.Map; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.BackendTypesystem; -import org.eclipse.xtend.backend.common.ExecutionContext; -import org.eclipse.xtend.backend.common.NamedFunction; -import org.eclipse.xtend.backend.common.Property; -import org.eclipse.xtend.backend.common.StaticProperty; import org.eclipse.xtend.backend.functions.java.internal.JavaBuiltinConverterFactory; -import org.eclipse.xtend.backend.types.builtin.VoidType; +import org.eclipse.xtend.backend.types.AbstractType; import org.eclipse.xtend.backend.util.ErrorHandler; @@ -38,52 +28,54 @@ import org.eclipse.xtend.backend.util.ErrorHandler; * * @author Arno Haase (http://www.haase-consulting.com) */ -public final class JavaBeansType implements BackendType { +public final class JavaBeansType extends AbstractType { private final Class<?> _javaClass; - private final List<NamedFunction> _operations = new ArrayList<NamedFunction>(); - private final Map<String, JavaBeansProperty> _properties = new HashMap<String, JavaBeansProperty> (); - private final Map<String, StaticProperty> _staticProperties = new HashMap<String, StaticProperty> (); - - private Collection<BackendType> _superTypes; - - public JavaBeansType (Class<?> cls) { - _javaClass = cls; + + public JavaBeansType (Class<?> javaCls, BackendTypesystem ts) { + super (javaCls.getName().replace(".", "::"), AbstractJavaBeansTypesystem.UNIQUE_REPRESENTATION_PREFIX + javaCls.getName(), superTypes(javaCls, ts)); + + _javaClass = javaCls; } + + private static BackendType[] superTypes (Class<?> javaCls, BackendTypesystem ts) { + final List<Class<?>> resultRaw = new ArrayList<Class<?>> (Arrays.asList (javaCls.getInterfaces())); + + Class<?> superClass = javaCls.getSuperclass(); + if (superClass != null) + resultRaw.add (superClass); + final List<BackendType> result = new ArrayList<BackendType> (); + for (Class<?> cls: resultRaw) + result.add(ts.getRootTypesystem ().findType (cls)); + + return result.toArray (new BackendType[result.size()]); + } + /** * the actual initialization is separated to deal with circular dependencies of operations and/or * properties referring to this very same type. */ - void init (BackendTypesystem ts) throws IntrospectionException { - _superTypes = Collections.singleton (ts.getRootTypesystem().findType (_javaClass.getSuperclass())); - + void init (BackendTypesystem ts) { for (Method mtd: _javaClass.getMethods()) { if (mtd.getDeclaringClass() == Object.class) // toString is added as a syslib function continue; - + final List<BackendType> paramTypes = new ArrayList<BackendType> (); - + paramTypes.add (this); // first parameter is the object on which the method is called for (Class<?> cls: mtd.getParameterTypes()) { paramTypes.add (ts.getRootTypesystem().findType(cls)); } - - _operations.add (new NamedFunction (mtd.getName(), new JavaOperation (mtd, paramTypes, null))); - } - - for (PropertyDescriptor pd: Introspector.getBeanInfo(_javaClass).getPropertyDescriptors()) { - if (getDeclaringClass (pd) == Object.class) - continue; - - _properties.put (pd.getName(), new JavaBeansProperty (pd, this)); //TODO apply primitive type conversion! + + register (mtd.getName(), new JavaOperation (mtd, paramTypes, null)); } - + // static properties for (Field field: _javaClass.getFields()) { final int mod = field.getModifiers(); if (Modifier.isPublic(mod) && Modifier.isStatic(mod) && Modifier.isFinal(mod)) { try { - _staticProperties.put (field.getName(), new JavaBeansStaticProperty (field, this, ts.getRootTypesystem().findType (field.getType()), JavaBuiltinConverterFactory.getConverter (field.getType()))); + register (new JavaBeansStaticProperty (field, this, ts.getRootTypesystem().findType (field.getType()), JavaBuiltinConverterFactory.getConverter (field.getType()))); } catch (Exception e) { ErrorHandler.handle (e); } @@ -95,18 +87,12 @@ public final class JavaBeansType implements BackendType { if (enumValues != null) { for (Object o : enumValues) { final Enum<?> curEnum = (Enum<?>) o; - _staticProperties.put (curEnum.name(), new JavaBeansStaticProperty (this, ts.getRootTypesystem().findType(curEnum), curEnum.name(), curEnum)); + register (new JavaBeansStaticProperty (this, ts.getRootTypesystem().findType(curEnum), curEnum.name(), curEnum)); } } } - private Class<?> getDeclaringClass (PropertyDescriptor pd) { - if (pd.getReadMethod() != null) - return pd.getReadMethod().getDeclaringClass(); - - return pd.getWriteMethod().getDeclaringClass(); - } - + @Override public Object create () { try { return _javaClass.newInstance(); @@ -115,62 +101,19 @@ public final class JavaBeansType implements BackendType { return null; // to make the compiler happy - this is never executed } } - - public List<NamedFunction> getBuiltinOperations () { - return _operations; - } - - public Object getProperty (ExecutionContext ctx, Object o, String name) { - return findProperty(name).get (ctx, o); - } - - private Property findProperty (String name) { - final Property result = _properties.get (name); - if (result == null) - throw new IllegalArgumentException (" no property " + name + " for type " + getName()); - - return result; - } - - public void setProperty (ExecutionContext ctx, Object o, String name, Object value) { - findProperty(name).set (ctx, o, value); - } - - public boolean isAssignableFrom (BackendType other) { - if (other == VoidType.INSTANCE) - return true; - - if (! (other instanceof JavaBeansType)) - return false; - - final JavaBeansType jbt = (JavaBeansType) other; - return _javaClass.isAssignableFrom(jbt._javaClass); - } - - public String getName () { - return _javaClass.getCanonicalName().replace(".", "::"); - } - - public String getUniqueRepresentation () { - return AbstractJavaBeansTypesystem.UNIQUE_REPRESENTATION_PREFIX + _javaClass.getName(); - } - - public Map<String, ? extends Property> getProperties (ExecutionContext ctx) { - return _properties; - } - - public Map<String, ? extends StaticProperty> getStaticProperties () { - return _staticProperties; - } - - public Collection<BackendType> getSuperTypes () { - return _superTypes; - } @Override public String toString () { return "JavaBeansType[" + _javaClass.getName() + "]"; } + + @Override + public boolean equals (Object other) { + if (other == null || ! (other instanceof JavaBeansType)) + return false; + + return ((JavaBeansType) other)._javaClass.equals (_javaClass); + } } diff --git a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java index 8c24dd56..f13cd07e 100644 --- a/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java +++ b/plugins/org.eclipse.xtend.backend/src/org/eclipse/xtend/middleend/javaannotations/JavaFunctionClassContributor.java @@ -57,6 +57,9 @@ public final class JavaFunctionClassContributor implements LanguageSpecificMiddl public ParsedResource parseResource (String resourceName) { final ParsedResource result = new ParsedResource (); + if (classAsResource (Object.class).equals (resourceName)) + return result; + //TODO imports //TODO advice //TODO guards diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BeanWithSizeProperty.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BeanWithSizeProperty.java index 0c7ee1e4..13069881 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BeanWithSizeProperty.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/testhelpers/BeanWithSizeProperty.java @@ -21,6 +21,7 @@ import java.util.List; */ public class BeanWithSizeProperty { private long _size; + private String _writeOnly = ""; public BeanWithSizeProperty (long size) { _size = size; @@ -47,8 +48,31 @@ public class BeanWithSizeProperty { return "asdf" + s + getSize() + " - " + (getSize() - i); } + public String getReadonlyProp () { + return "r/o"; + } + + public void setWriteOnlyProp (String s) { + _writeOnly = s; + } + + public String getABCdef () { + return "ABC"; + } + + public boolean isXYZabc () { + return true; + } + + public boolean hasRS () { + return false; + } + + public void setR (String s) { + } + @Override public String toString () { - return "BeanWithSize [" + _size + "]"; + return "BeanWithSize [" + _size + ": " + _writeOnly + "]"; } } diff --git a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/types/JavaBeansTypeTest.java b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/types/JavaBeansTypeTest.java index 9927863d..6a62d1f4 100644 --- a/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/types/JavaBeansTypeTest.java +++ b/tests/org.eclipse.xtend.backend.test/src/org/eclipse/xtend/backend/types/JavaBeansTypeTest.java @@ -11,14 +11,23 @@ Contributors: package org.eclipse.xtend.backend.types; import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createEmptyExecutionContext; -import static org.junit.Assert.*; +import static org.eclipse.xtend.backend.testhelpers.BackendTestHelper.createLiteral; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; import java.util.Arrays; +import java.util.Map; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.BackendTypesystem; import org.eclipse.xtend.backend.common.ExecutionContext; +import org.eclipse.xtend.backend.common.NamedFunction; +import org.eclipse.xtend.backend.common.Property; +import org.eclipse.xtend.backend.functions.AbstractFunction; +import org.eclipse.xtend.backend.functions.FunctionDefContextInternal; import org.eclipse.xtend.backend.testhelpers.BeanWithSizeProperty; +import org.eclipse.xtend.backend.types.builtin.ObjectType; +import org.eclipse.xtend.backend.types.emf.EmfTypesystem; import org.junit.Test; /** @@ -41,4 +50,78 @@ public class JavaBeansTypeTest { assertEquals ("{javabean}" + BeanWithSizeProperty.class.getName(), byClass.getUniqueRepresentation()); } + + @Test + public void testInterface () { + final CompositeTypesystem typeSystem = new CompositeTypesystem (); + typeSystem.register (new EmfTypesystem ()); + + final BackendType interfaceType = typeSystem.findType (org.eclipse.xtend.backend.syslib.Outlet.class); + assertEquals (1, interfaceType.getSuperTypes().size ()); + assertEquals (ObjectType.INSTANCE, interfaceType.getSuperTypes().iterator().next()); + } + + @Test + public void testProperties () { + final BackendTypesystem ts = new CompositeTypesystem (); + + final BackendType type = ts.findType (BeanWithSizeProperty.class); + final Map<String, ? extends Property> props = type.getProperties (createEmptyExecutionContext()); + + System.out.println (props.keySet()); + assertEquals (8, props.size()); + + final Object o = new BeanWithSizeProperty (4); + + final Property sizeProp = props.get ("size"); + checkProp (sizeProp, "size", type, true, true); + assertEquals (4L, sizeProp.get(createEmptyExecutionContext(), o)); + sizeProp.set(createEmptyExecutionContext(), o, 3L); + assertEquals (3L, sizeProp.get(createEmptyExecutionContext(), o)); + + checkProp (props.get ("chunks"), "chunks", type, true, false); + assertEquals (Arrays.asList("a0", "a1", "a2"), type.getProperty(createEmptyExecutionContext(), o, "chunks")); + + checkProp (props.get ("readonlyProp"), "readonlyProp", type, true, false); + checkProp (props.get ("writeOnlyProp"), "writeOnlyProp", type, false, true); + + checkProp (props.get ("ABCdef"), "ABCdef", type, true, false); + checkProp (props.get ("XYZabc"), "XYZabc", type, true, false); + checkProp (props.get ("RS"), "RS", type, true, false); + checkProp (props.get ("r"), "r", type, false, true); + + final ExecutionContext ctx = createEmptyExecutionContext(); + ((FunctionDefContextInternal) ctx.getFunctionDefContext()).register (new NamedFunction ("getZoom", new AbstractFunction (null, Arrays.asList(type), false) { + public Object invoke (ExecutionContext pCtx, Object[] params) { + return "zoom"; + } + }), true); + ((FunctionDefContextInternal) ctx.getFunctionDefContext()).register (new NamedFunction ("getWithGuard", new AbstractFunction (createLiteral(Boolean.TRUE), Arrays.asList(type), false) { + public Object invoke (ExecutionContext pCtx, Object[] params) { + return "yxy"; + } + }), true); + ((FunctionDefContextInternal) ctx.getFunctionDefContext()).register (new NamedFunction ("getPrivate", new AbstractFunction (null, Arrays.asList(type), false) { + public Object invoke (ExecutionContext pCtx, Object[] params) { + return "asdf"; + } + }), false); + + assertEquals (10, type.getProperties (ctx).size()); + + assertEquals ("zoom", ctx.getFunctionDefContext().invoke (ctx, "getZoom", Arrays.asList (o))); + final Property zoomProperty = type.getProperties (ctx).get ("zoom"); + checkProp (zoomProperty, "zoom", type, true, false); + assertEquals ("zoom", zoomProperty.get (ctx, o)); + assertEquals ("zoom", type.getProperty (ctx, o, "zoom")); + + checkProp (type.getProperties (ctx).get ("private"), "private", type, true, false); + } + + private void checkProp (Property prop, String name, BackendType owner, boolean isReadable, boolean isWritable) { + assertEquals (name, prop.getName()); + assertEquals (owner, prop.getOwner()); + assertEquals (isReadable, prop.isReadable()); + assertEquals (isWritable, prop.isWritable()); + } } |