package org.eclipse.xtend.middleend.xtend.internal.xtendlib; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.eclipse.xtend.backend.aop.ThisJoinPoint; import org.eclipse.xtend.backend.aop.ThisJoinPointStaticPart; import org.eclipse.xtend.backend.common.BackendType; import org.eclipse.xtend.backend.common.ExecutionContext; import org.eclipse.xtend.backend.common.Function; import org.eclipse.xtend.backend.common.NamedFunction; import org.eclipse.xtend.backend.common.Property; import org.eclipse.xtend.backend.common.QualifiedName; import org.eclipse.xtend.backend.common.StaticProperty; import org.eclipse.xtend.backend.common.SyntaxConstants; import org.eclipse.xtend.backend.syslib.CollectionOperations; import org.eclipse.xtend.backend.syslib.SysLibNames; import org.eclipse.xtend.backend.types.builtin.CollectionType; import org.eclipse.xtend.backend.types.builtin.FunctionType; import org.eclipse.xtend.backend.types.builtin.ObjectType; import org.eclipse.xtend.backend.types.builtin.PropertyType; import org.eclipse.xtend.backend.types.builtin.StaticPropertyType; import org.eclipse.xtend.backend.types.emf.EObjectType; import org.eclipse.xtend.backend.types.java.internal.JavaBeansType; import org.eclipse.xtend.middleend.javaannotations.AbstractExecutionContextAware; import org.eclipse.xtend.middleend.javaannotations.M2tCached; public class XtendBuiltinOperations extends AbstractExecutionContextAware { @SuppressWarnings("unchecked") public Long xtendCompareTo (Object target, Object o) { if (target == null) return o == null ? new Long(0) : new Long(-1); if (o == null) return new Long(1); if (target instanceof Comparable) return new Long(((Comparable<Object>) target).compareTo(o)); else { final String s1 = (String)_ctx.getFunctionDefContext ().invoke (_ctx, new QualifiedName ("toString"), Arrays.asList(target)); final String s2 = (String)_ctx.getFunctionDefContext ().invoke (_ctx, new QualifiedName ("toString"), Arrays.asList(target)); return new Long(s1.compareTo(s2)); } } public BackendType XtendMetaType (Object o) { return _ctx.getTypesystem().findType(o); } @M2tCached public String XtendStringReplaceFirst (String s, String regex, String replacement) { return s.replaceFirst(regex, replacement); } @M2tCached public List<Long> XtendUpto (Long target, Long v) { final List<Long> result = new ArrayList<Long>(); Long l1 = target; while (l1.compareTo(v) <= 0) { result.add(l1); l1 = l1++; } return result; } @M2tCached public List<Integer> XtendUpto (Integer target, Integer v) { final List<Integer> result = new ArrayList<Integer>(); Integer l1 = target; while (l1.compareTo(v) <= 0) { result.add(l1); l1++; } return result; } @M2tCached public List<Long> XtendUpto (Long target, Long v, Long inc) { final List<Long> result = new ArrayList<Long>(); Long l1 = target; while (l1.compareTo(v) <= 0) { result.add(l1); l1 = l1 + inc; } return result; } @M2tCached public List<Integer> XtendUpto (Integer target, Integer v, Integer inc) { final List<Integer> result = new ArrayList<Integer>(); Integer l1 = target; while (l1.compareTo(v) <= 0) { result.add(l1); l1 = l1 + inc; } return result; } public Set<StaticProperty> XtendTypeAllStaticProperties (BackendType target) { Set<StaticProperty> result = new HashSet<StaticProperty>(); result.addAll (target.getStaticProperties ().values()); for (BackendType superType : target.getSuperTypes()) { result.addAll (superType.getStaticProperties ().values()); } return result; } @SuppressWarnings("unchecked") public Set XtendTypeAllFeatures (BackendType target) { Set result = new HashSet (); result.addAll (XtendTypeAllProperties (target)); result.addAll (XtendTypeAllOperations (target)); result.addAll (XtendTypeAllStaticProperties (target)); return result; } public Set<NamedFunction> XtendTypeAllOperations (BackendType target) { Set<NamedFunction> result = new HashSet<NamedFunction>(); Collection<? extends NamedFunction> builtinOps = target.getBuiltinOperations(); for (NamedFunction f : builtinOps) { if (isXtendOperation(target, f)) result.add (f); } result.addAll(target.getBuiltinOperations()); Collection<? extends BackendType> superTypes = target.getSuperTypes(); for (BackendType backendType : superTypes) { Collection<? extends NamedFunction> superTypeOps = backendType.getBuiltinOperations(); Collection<NamedFunction> funcs =_ctx.getFunctionDefContext().getByFirstParameterType (backendType); for (NamedFunction namedFunction : funcs) { if (isXtendOperation(target, namedFunction)) result.add (namedFunction); } } return result; } public Set<Object> XtendTypeAllProperties (BackendType target) { Set<Object> result = new HashSet<Object>(); result.addAll (target.getProperties (_ctx).values()); for (BackendType superType : target.getSuperTypes()) { result.addAll (superType.getProperties (_ctx).values()); } Set<NamedFunction> accessors = XtendTypeAllOperations (target); for (NamedFunction accessorFunc : accessors) { if (isFunctionBackedProperty (accessorFunc)) result.add (accessorFunc); } return result; } public Set<BackendType> XtendTypeSuperTypes (BackendType target) { Set<BackendType> result = new HashSet<BackendType>(); result.addAll(target.getSuperTypes()); return result; } public String XtendTypeDocumentation (BackendType target) { return ""; } public String XtendTypeDocumentation (Object target) { return ""; } public String XtendTypeDocumentation (EObjectType target) { return "base type for all ecore based metamodels (added by oAW4 emftools)"; } public String XtendTypeDocumentation (JavaBeansType target) { return ""; } public String XtendTypeDocumentation (NamedFunction target) { return ""; } public String XtendTypeDocumentation (Property target) { return ""; } public String XtendTypeDocumentation (StaticProperty target) { return ""; } public Object XtendTypeGetProperty (BackendType target, CharSequence propertyName) { final QualifiedName xtendNameFunc = new QualifiedName (XtendLibNames.OPERATION_NAME); for (Property prop : target.getProperties (_ctx).values()) { final String name = (String) _ctx.getFunctionDefContext().invoke(_ctx, xtendNameFunc, Arrays.asList(prop)); if (propertyName.toString().equals(name)) return prop; } for (BackendType superType : XtendTypeSuperTypes(target)) { for (Property prop : superType.getProperties (_ctx).values()) { final String name = (String) _ctx.getFunctionDefContext().invoke(_ctx, xtendNameFunc, Arrays.asList(prop)); if (propertyName.toString().equals(name)) return prop; } } NamedFunction builtinFunc = XtendTypeGetOperation(target, propertyName.toString(), new ArrayList<BackendType>()); if (isXtendOperation(target, builtinFunc)) return builtinFunc; return null; } public Object XtendTypeGetFeature (BackendType target, String featureName, List<BackendType> paramTypes) { final QualifiedName xtendNameFunc = new QualifiedName (XtendLibNames.OPERATION_NAME); for (Property prop : target.getProperties (_ctx).values()) { final String name = (String) _ctx.getFunctionDefContext().invoke(_ctx, xtendNameFunc, Arrays.asList(prop)); if (featureName.equals(name)) return prop; } for (StaticProperty staticProp : target.getStaticProperties().values()) { final String name = (String) _ctx.getFunctionDefContext().invoke(_ctx, xtendNameFunc, Arrays.asList(staticProp)); if (featureName.equals(name)) return staticProp; } NamedFunction builtinFunc = XtendTypeGetOperation(target, featureName, paramTypes); if (builtinFunc != null) return builtinFunc; for (BackendType superType : XtendTypeSuperTypes(target)) { for (Property prop : superType.getProperties (_ctx).values()) { final String name = (String) _ctx.getFunctionDefContext().invoke(_ctx, xtendNameFunc, Arrays.asList(prop)); if (featureName.equals(name)) return prop; } for (StaticProperty staticProp : target.getStaticProperties().values()) { final String name = (String) _ctx.getFunctionDefContext().invoke(_ctx, xtendNameFunc, Arrays.asList(staticProp)); if (featureName.equals(name)) return staticProp; } } return null; } @SuppressWarnings("unchecked") public NamedFunction XtendTypeGetOperation (BackendType target, String functionName, List<BackendType> paramTypes) { List<BackendType> pTypes = new LinkedList<BackendType>(); pTypes.add(0, target); pTypes.addAll(paramTypes); String convertedName = toBackendBuiltinFeatureName (functionName); if (convertedName == null) convertedName = functionName; Collection<NamedFunction> canditates = (Collection<NamedFunction>) _ctx.getFunctionDefContext().invoke (_ctx, new QualifiedName (XtendLibNames.TYPE_ALL_OPERATIONS), Arrays.asList (target)); canditates.addAll (_ctx.getFunctionDefContext ().getByFirstParameterType (target)); Function matchedInnerFunc = _ctx.getFunctionDefContext ().getMatch (_ctx, new QualifiedName (functionName), pTypes); if (matchedInnerFunc == null) matchedInnerFunc = _ctx.getFunctionDefContext ().getMatch (_ctx, new QualifiedName ( convertedName), pTypes); for (NamedFunction f : canditates) { if (f.getFunction().equals (matchedInnerFunc)) return f; } //TODO Exception handling return null; } public List<? extends BackendType> XtendOperationGetParameterTypes (NamedFunction target) { List<? extends BackendType> params = target.getFunction().getParameterTypes (); return params.subList (1, params.size ()); } @SuppressWarnings("unchecked") public Object XtendOperationEvaluate (NamedFunction f, Object target, List params) { params.add(0, target); return _ctx.getFunctionInvoker().invoke(_ctx, f.getFunction(), params); } public BackendType XtendFeatureReturnType (NamedFunction f) { return f.getFunction().getReturnType(); } public BackendType XtendFeatureReturnType (Property p) { return p.getType (_ctx.getTypesystem()); } public BackendType XtendFeatureReturnType (StaticProperty p) { return p.getType (); } public BackendType XtendFeatureOwner (Property target) { return target.getOwner(); } public BackendType XtendFeatureOwner (StaticProperty target) { return target.getOwner(); } public BackendType XtendFeatureOwner (NamedFunction target) { return target.getFunction().getParameterTypes().get(0); } public Object XtendName (NamedFunction f) { final String name = f.getName().getFullQualifiedName(); final String xpandName = toXpandBuiltinFeatureName(name); if (xpandName != null) return xpandName; return name; } public Object XtendName (Property p) { final String name = p.getName(); final String xpandName = toXpandBuiltinFeatureName(name); if (xpandName != null) return xpandName; return name; } public Object XtendName (StaticProperty p) { final String name = p.getName(); final String xpandName = toXpandBuiltinFeatureName(name); if (xpandName != null) return xpandName; return name; } public Object XtendName (Object target) { final BackendType t = _ctx.getTypesystem().findType (target); if (CollectionType.INSTANCE.isAssignableFrom(t)) { if (isProperty (_ctx, t, "name")) return t.getProperty (_ctx, target, "name"); final Collection<Object> result = CollectionOperations.createMatchingCollection ((Collection<?>) target); for (Object obj: (Collection<?>) target) { Object[] args = {obj}; CollectionOperations.addFlattened(result, _ctx.getFunctionDefContext() .getMatch(_ctx, new QualifiedName (XtendLibNames.OPERATION_NAME), Arrays.asList (_ctx.getTypesystem().findType (obj))) .invoke(_ctx, args)); } return result; } else return t.getProperty (_ctx, target, "name"); } public List<?> adviceCtxParamValues (ThisJoinPoint jp) { return jp.getParameters(); } public List<? extends BackendType> adviceCtxParamTypes (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) return joinPointStaticPart.getFunction().getParameterTypes(); return null; } @SuppressWarnings("unchecked") public List<String> adviceCtxParamNames (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) { return (List<String>) _ctx.getFunctionDefContext().invoke (_ctx, new QualifiedName (SysLibNames.OPERATION_PARAM_NAMES), Arrays.asList(joinPointStaticPart.getFunction())); } return null; } public String xtendDefinitionName (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) { Function f = joinPointStaticPart.getFunction(); BackendType targetType = f.getParameterTypes().get(0); Collection<NamedFunction> canditates = _ctx.getFunctionDefContext().getByFirstParameterType(targetType); for (NamedFunction namedFunction : canditates) { if (namedFunction.getFunction ().equals (f)) return namedFunction.getName ().getFullQualifiedName(); } } return null; } public Object xtendDefinitionToString (ThisJoinPoint jp) { if (jp.getParameters().size() > 0) { Object target = jp.getParameters().get(0); return _ctx.getFunctionDefContext().invoke(_ctx, new QualifiedName ("toString"), Arrays.asList(target)); } return null; } public String adviceCtxName (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) { return joinPointStaticPart.getFunctionName ().getFullQualifiedName(); } return null; } public List<? extends BackendType> xtendDefinitionParamTypes (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) { List<? extends BackendType> parameterTypes = joinPointStaticPart.getFunction().getParameterTypes(); return parameterTypes.subList(1, parameterTypes.size()); } return null; } public BackendType adviceCtxTargetType (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) { List<? extends BackendType> parameterTypes = joinPointStaticPart.getFunction().getParameterTypes(); if (parameterTypes != null && parameterTypes.size() > 0) return parameterTypes.get(0); } return null; } @SuppressWarnings("unchecked") public List<String> xtendDefinitionParamNames (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) { List<String> paramNames = (List<String>) _ctx.getFunctionDefContext().invoke (_ctx, new QualifiedName (SysLibNames.OPERATION_PARAM_NAMES), Arrays.asList(joinPointStaticPart.getFunction())); if (paramNames != null) return paramNames.subList(1, paramNames.size()); } return null; } public Object XtendName (ThisJoinPoint jp) { final ThisJoinPointStaticPart joinPointStaticPart = (ThisJoinPointStaticPart) _ctx.getLocalVarContext ().getLocalVars ().get (SyntaxConstants.THIS_JOINPOINT_STATICPART); if (joinPointStaticPart != null) return joinPointStaticPart.getFunctionName().getFullQualifiedName(); return null; } private boolean isProperty (ExecutionContext ctx, BackendType t, String propName) { return t.getProperties(ctx).containsKey (propName); } private boolean isFunctionBackedProperty (NamedFunction f) { BackendType targetType = f.getFunction().getParameterTypes().get(0); if (f.getName().getFullQualifiedName().equals (XtendLibNames.OPERATION_NAME)) { if (targetType.equals(ObjectType.INSTANCE)) return false; else return true; } if (f.getName().getFullQualifiedName().equals(XtendLibNames.OBJECT_META_TYPE)) return true; if (f.getName().getFullQualifiedName().equals(XtendLibNames.ITERATOR_ELEMENTS)) return true; if (f.getName().getFullQualifiedName().equals(XtendLibNames.TYPE_ALL_FEATURES)) return true; if (f.getName().getFullQualifiedName().equals(XtendLibNames.TYPE_ALL_OPERATIONS)) return true; if (f.getName().getFullQualifiedName().equals(XtendLibNames.TYPE_ALL_PROPERTIES)) return true; if (f.getName().getFullQualifiedName().equals(XtendLibNames.TYPE_ALL_STATIC_PROPERTIES)) return true; if (f.getName().getFullQualifiedName().equals(XtendLibNames.TYPE_SUPER_TYPES)) return true; return false; } private boolean isXtendOperation (BackendType target, NamedFunction f) { BackendType funcTargetType = f.getFunction().getParameterTypes().get(0); if (f.getName().getFullQualifiedName().equals (XtendLibNames.OPERATION_NAME)) { if (FunctionType.INSTANCE.isAssignableFrom(funcTargetType)) return true; else if (PropertyType.INSTANCE.isAssignableFrom(funcTargetType)) return true; else if (StaticPropertyType.INSTANCE.isAssignableFrom(funcTargetType)) return true; else return false; } if (f.getName().getFullQualifiedName().equals("concat") && funcTargetType.equals(ObjectType.INSTANCE) && !target.getBuiltinOperations().contains(f)) return false; return true; } private String toBackendBuiltinFeatureName (final String name) { if (name.equals ("name")) return XtendLibNames.OPERATION_NAME; if (name.equals ("metaType")) return XtendLibNames.OBJECT_META_TYPE; if (name.equals ("allFeatures")) return XtendLibNames.TYPE_ALL_FEATURES; if (name.equals ("allOperations")) return XtendLibNames.TYPE_ALL_OPERATIONS; if (name.equals ("allProperties")) return XtendLibNames.TYPE_ALL_PROPERTIES; if (name.equals ("elements")) return XtendLibNames.ITERATOR_ELEMENTS; if (name.equals ("<")) return SysLibNames.OPERATOR_LESS; if (name.equals (">")) return SysLibNames.OPERATOR_GREATER; if (name.equals ("<=")) return SysLibNames.OPERATOR_LESS_OR_EQUALS; if (name.equals(">=")) return SysLibNames.OPERATOR_GREATER_OR_EQUALS; if (name.equals ("==")) return SysLibNames.OPERATOR_EQUALS; if (name.equals ("!=")) return SysLibNames.OPERATOR_NOT_EQUALS; if (name.equals ("!")) return SysLibNames.OPERATOR_NOT; if (name.equals ("+")) return SysLibNames.OPERATOR_PLUS; if (name.equals ("-")) return SysLibNames.OPERATOR_MINUS; if (name.equals ("*")) return SysLibNames.OPERATOR_MULT; if (name.equals ("/")) return SysLibNames.OPERATOR_DIV; if (name.equals ("%")) return SysLibNames.OPERATOR_MOD; if (name.equals ("compareTo")) return XtendLibNames.COMPARE_TO; if (name.equals ("add")) return XtendLibNames.ADD; if (name.equals ("addAll")) return XtendLibNames.ADD_ALL; if (name.equals ("remove")) return XtendLibNames.REMOVE; if (name.equals ("removeAll")) return XtendLibNames.REMOVE_ALL; return null; } private String toXpandBuiltinFeatureName(final String name) { if (name.equals(XtendLibNames.OPERATION_NAME)) return "name"; if (name.equals(XtendLibNames.OBJECT_META_TYPE)) return "metaType"; if (name.equals(XtendLibNames.TYPE_ALL_FEATURES)) return "allFeatures"; if (name.equals(XtendLibNames.TYPE_ALL_OPERATIONS)) return "allOperations"; if (name.equals(XtendLibNames.TYPE_ALL_PROPERTIES)) return "allProperties"; if (name.equals(XtendLibNames.ITERATOR_ELEMENTS)) return "elements"; if (name.equals(SysLibNames.OPERATOR_LESS)) return "<"; if (name.equals(SysLibNames.OPERATOR_GREATER)) return ">"; if (name.equals(SysLibNames.OPERATOR_LESS_OR_EQUALS)) return "<="; if (name.equals(SysLibNames.OPERATOR_GREATER_OR_EQUALS)) return ">="; if (name.equals(SysLibNames.OPERATOR_EQUALS)) return "=="; if (name.equals(SysLibNames.OPERATOR_NOT_EQUALS)) return "!="; if (name.equals(SysLibNames.OPERATOR_NOT)) return "!"; if (name.equals(SysLibNames.OPERATOR_PLUS)) return "+"; if (name.equals(SysLibNames.OPERATOR_MINUS)) return "-"; if (name.equals(SysLibNames.OPERATOR_MULT)) return "*"; if (name.equals(SysLibNames.OPERATOR_DIV)) return "/"; if (name.equals(SysLibNames.OPERATOR_MOD)) return "%"; if (name.equals(XtendLibNames.COMPARE_TO)) return "compareTo"; if (name.equals(XtendLibNames.ADD)) return "add"; if (name.equals(XtendLibNames.ADD_ALL)) return "addAll"; if (name.equals(XtendLibNames.REMOVE)) return "remove"; if (name.equals(XtendLibNames.REMOVE_ALL)) return "removeAll"; return null; } }