/** * Abstract Java Method * * @author Martin Bravenboer <martin@cs.uu.nl> */ module dryad/model/method imports dryad/model/member dryad/lib-ext/oo/classes /** * Names */ strategies /** * Returns the MethodName of this method. * * Note that a MethodName not uniquely identifies a method * (i.e. a different method can have the same name). * * @type Method Object -> MethodName */ get-name = instanceof-JavaMethod; ?this; where(get-declaring-class => class) ; !MethodName(<get-canonical-name> class, Id(<get-simple-name> this)) /** * Return name that uniquely identifiers a method. * * Note that the JLS does not define canonical names for methods. * We just use the same terminology for this unique method name, to * avoid another kind of name. * * @todo Include type parameters one way or another? */ get-canonical-name = instanceof-JavaMethod; ?this; !MethodName( <get-declaring-class; get-canonical-name> this , Id(<get-simple-name> this) , <get-formal-parameter-types> this , <get-return-type> this ) /** * Access */ strategies /** * Returns the access of this method. * Must be implemented by subclasses. * * @type Method object -> Access Modifier */ get-access = fail /** * Formal type parameters * * @todo Same code as for classes. Make this a superclass? */ strategies /** * Succeeds if this class has a type parameter of the given name. * * @param Simple name of the type parameter (String) * @type Method Object -> TypeParam */ has-formal-type-parameter(|name) = instanceof-JavaMethod; where(get-formal-type-parameter(|name)) /** * Returns the type parameter of the given name, or fails * if this class thus have a type parameter with this name. * * @param Simple name of the type parameter (String) * @type Method Object -> TypeParam */ get-formal-type-parameter(|name) = instanceof-JavaMethod; get-formal-type-parameters ; fetch-elem(?TypeParam(Id(name), _)) /** * Abstract method. Has to declared in subclasses. * * @type Method Object -> List(TypeParam) */ get-formal-type-parameters = fail /** * Succeeds if this is a generic method (i.e. has formal type parameters). */ is-generic = instanceof-JavaMethod; where(get-formal-type-parameters => [_ | _]) /** * Return Type */ strategies get-return-type(|inclass) = get-return-type-in-class(|inclass) get-return-type(|intype) = get-return-type-in-type(|intype) /** * Returns the return type of this method if this method is invoked * as a member of the given class. * * If the method is not actually a member of the specified class, then * this strategy will fail. * * @param Class Object */ get-return-type-in-class(|inclass) = instanceof-JavaMethod; ?this; where(get-simple-name => name); get-member-type-in-class-helper( get-declared-methods(|name) , get-return-type , get-return-type-in-type | inclass ) /** * Returns the return type of this method if this method is invoked * as a member of the given type. * * If the method is not actually a member of the specified type, then * this strategy will fail. * * @param Type */ get-return-type-in-type(|intype) = instanceof-JavaMethod; ?this; where(<is-reference-type> intype) ; get-member-type-in-type-helper(get-return-type-in-class | intype) /** * Formal Parameters */ strategies /** * Succeeds if this method does not take a variable number of arguments. */ is-fixed-arity-method = not(is-variable-arity-method) get-formal-parameter-types(|inclass) = get-formal-parameter-types-in-class(|inclass) get-formal-parameter-types(|intype) = get-formal-parameter-types-in-type(|intype) /** * Returns the formal parameter types of this method if this method is * invoked as a member of the given class. * * If the method is not actually a member of the specified class, then * this strategy will fail. * * @param Class Object * @type Method Object -> List(Type) */ get-formal-parameter-types-in-class(|inclass) = instanceof-JavaMethod; ?this; where(get-simple-name => name); get-member-type-in-class-helper( get-declared-methods(|name) , get-formal-parameter-types , get-formal-parameter-types-in-type | inclass ) /** * Returns the formal parameter types of this method if this method is invoked * as a member of the given type. * * If the method is not actually a member of the specified type, then * this strategy will fail. * * @param Type * @type Method Object -> List(Type) */ get-formal-parameter-types-in-type(|intype) = instanceof-JavaMethod; ?this; where(<is-reference-type> intype) ; get-member-type-in-type-helper(get-formal-parameter-types-in-class | intype) strategies /** * @todo Reuse define-substition. * @todo Raw types and type erasure. * @todo Check the bound * @todo Does zip check that the number of arguments are equal? */ get-member-type-in-type-helper(getter : ClassObject * MethodObject -> a | intype) = ?this; !intype; if ?InterfaceType(typename, None()) + ?ClassType(typename, None()) then where(<lookup-class> typename => c) ; <getter(|c)> this ; if <is-generic> c then if is-list then map(type-erasure) else type-erasure end end else {| LookupTypeVar : ( ?InterfaceType(typename, Some(TypeArgs(t*))) + ?ClassType(typename, Some(TypeArgs(t*)))) ; where(<lookup-class> typename => c) ; <get-formal-type-parameters> c => a* ; <zip> (t*, a*) ; map({t, a: ?(t, TypeParam(Id(a), _)) ; rules(LookupTypeVar : TypeVar(typename, Id(a)) -> t) }) ; <getter(|c)> this |} end /** * OMG! */ get-member-type-in-class-helper( declaredgetter : ClassObject -> List(MemberObject) , resultgetter : MemberObject -> a , typegetter : ClassObject * MethodObject -> a | inclass) = ?this ; <instanceof-JavaClass> inclass ; ( <declaredgetter> inclass ; fetch(?this) ; <resultgetter> this ; topdown(try(LookupTypeVar)) <+ <get-superclass-as-type> inclass ; topdown(try(LookupTypeVar)) => super ; <typegetter(|super)> this <+ get-superinterfaces-as-type ; fetch-elem({interface: ?interface; <typegetter(|interface)> this}) ) /** * Stratego class support. */ strategies /** * Checks if current term is an instance of JavaClass. * * Subclasses of method implement this strategy. */ instanceof-JavaMethod = fail /** * Every Java method is a Java member. */ instanceof-JavaMember = instanceof-JavaMethod