001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     *                    2015, Jesper �qvist <jesper.oqvist@cs.lth.se>
003     * All rights reserved.
004     *
005     * Redistribution and use in source and binary forms, with or without
006     * modification, are permitted provided that the following conditions are met:
007     *
008     * 1. Redistributions of source code must retain the above copyright notice,
009     * this list of conditions and the following disclaimer.
010     *
011     * 2. Redistributions in binary form must reproduce the above copyright notice,
012     * this list of conditions and the following disclaimer in the documentation
013     * and/or other materials provided with the distribution.
014     *
015     * 3. Neither the name of the copyright holder nor the names of its
016     * contributors may be used to endorse or promote products derived from this
017     * software without specific prior written permission.
018     *
019     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
023     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
024     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
025     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
026     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
027     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
029     * POSSIBILITY OF SUCH DAMAGE.
030     */
031    
032    aspect MethodSignature15 {
033      refine LookupMethod protected SimpleSet MethodAccess.maxSpecific(Collection candidates) {
034        SimpleSet potentiallyApplicable = potentiallyApplicable(candidates);
035        // first phase
036        SimpleSet maxSpecific = applicableBySubtyping(potentiallyApplicable);
037        // second phase
038        maxSpecific = applicableByMethodInvocationConversion(potentiallyApplicable, maxSpecific);
039        // third phase
040        maxSpecific = applicableVariableArity(potentiallyApplicable, maxSpecific);
041        return maxSpecific;
042      }
043    
044      protected SimpleSet MethodAccess.potentiallyApplicable(Collection candidates) {
045        SimpleSet potentiallyApplicable = SimpleSet.emptySet;
046        // select potentially applicable methods
047        for (Iterator iter = candidates.iterator(); iter.hasNext(); ) {
048          MethodDecl decl = (MethodDecl) iter.next();
049          if (potentiallyApplicable(decl) && accessible(decl)) {
050            if (decl.isGeneric()) {
051              GenericMethodDecl gm = decl.genericDecl();
052              decl = gm.lookupParMethodDecl(
053                  inferTypeArguments(
054                      gm.type(),
055                      gm.getParameterList(),
056                      getArgList(),
057                      gm.getTypeParameterList()));
058            }
059            potentiallyApplicable = potentiallyApplicable.add(decl);
060          }
061        }
062        return potentiallyApplicable;
063      }
064    
065      protected SimpleSet MethodAccess.applicableBySubtyping(SimpleSet potentiallyApplicable) {
066        SimpleSet maxSpecific = SimpleSet.emptySet;
067        for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
068          MethodDecl decl = (MethodDecl) iter.next();
069          if (applicableBySubtyping(decl)) {
070            maxSpecific = mostSpecific(maxSpecific, decl);
071          }
072        }
073        return maxSpecific;
074      }
075    
076      protected SimpleSet MethodAccess.applicableByMethodInvocationConversion(
077          SimpleSet potentiallyApplicable, SimpleSet maxSpecific) {
078        if (maxSpecific.isEmpty()) {
079          for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
080            MethodDecl decl = (MethodDecl) iter.next();
081            if (applicableByMethodInvocationConversion(decl)) {
082              maxSpecific = mostSpecific(maxSpecific, decl);
083            }
084          }
085        }
086        return maxSpecific;
087      }
088    
089      protected SimpleSet MethodAccess.applicableVariableArity(SimpleSet potentiallyApplicable,
090          SimpleSet maxSpecific) {
091        if (maxSpecific.isEmpty()) {
092          for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
093            MethodDecl decl = (MethodDecl) iter.next();
094            if (decl.isVariableArity() && applicableVariableArity(decl)) {
095              maxSpecific = mostSpecific(maxSpecific, decl);
096            }
097          }
098        }
099        return maxSpecific;
100      }
101    
102      refine ConstructScope eq ClassInstanceExpr.decls() {
103        TypeDecl typeDecl = hasTypeDecl() ? getTypeDecl() : getAccess().type();
104        return chooseConstructor(typeDecl.constructors(), getArgList());
105      }
106    
107      refine ConstructScope eq ConstructorAccess.decls() =
108          chooseConstructor(lookupConstructor(), getArgList());
109    
110      refine ConstructScope eq SuperConstructorAccess.decls() {
111        Collection c = hasPrevExpr() && !prevExpr().isTypeAccess()
112            ? hostType().lookupSuperConstructor()
113            : lookupSuperConstructor();
114        return chooseConstructor(c, getArgList());
115      }
116    
117      refine AnonymousClasses eq ClassInstanceExpr.getTypeDecl().constructorDecl() {
118        Collection c = getAccess().type().constructors();
119        SimpleSet maxSpecific = chooseConstructor(c, getArgList());
120        if (maxSpecific.size() == 1) {
121          return (ConstructorDecl) maxSpecific.iterator().next();
122        }
123        return unknownConstructor();
124      }
125    
126      protected SimpleSet Expr.chooseConstructor(Collection constructors, List<Expr> argList) {
127        SimpleSet potentiallyApplicable = SimpleSet.emptySet;
128    
129        // Select potentially applicable constructors.
130        for (Iterator iter = constructors.iterator(); iter.hasNext(); ) {
131          ConstructorDecl decl = (ConstructorDecl) iter.next();
132          if (decl.potentiallyApplicable(argList) && decl.accessibleFrom(hostType())) {
133            if (decl.isGeneric()) {
134              GenericConstructorDecl gc = decl.genericDecl();
135              decl = gc.lookupParConstructorDecl(
136                  inferTypeArguments(
137                      gc.type(),
138                      gc.getParameterList(),
139                      argList,
140                      gc.getTypeParameterList()));
141            }
142            potentiallyApplicable = potentiallyApplicable.add(decl);
143          }
144        }
145    
146        // First phase.
147        SimpleSet maxSpecific = SimpleSet.emptySet;
148        for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
149          ConstructorDecl decl = (ConstructorDecl) iter.next();
150          if (decl.applicableBySubtyping(argList)) {
151            maxSpecific = mostSpecific(maxSpecific, decl);
152          }
153        }
154    
155        // Second phase.
156        if (maxSpecific.isEmpty()) {
157          for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
158            ConstructorDecl decl = (ConstructorDecl) iter.next();
159            if (decl.applicableByMethodInvocationConversion(argList)) {
160              maxSpecific = mostSpecific(maxSpecific, decl);
161            }
162          }
163        }
164    
165        // Third phase.
166        if (maxSpecific.isEmpty()) {
167          for (Iterator iter = potentiallyApplicable.iterator(); iter.hasNext(); ) {
168            ConstructorDecl decl = (ConstructorDecl) iter.next();
169            if (decl.isVariableArity() && decl.applicableVariableArity(argList)) {
170              maxSpecific = mostSpecific(maxSpecific, decl);
171            }
172          }
173        }
174        return maxSpecific;
175      }
176    
177      protected static SimpleSet Expr.mostSpecific(SimpleSet maxSpecific, ConstructorDecl decl) {
178        if (maxSpecific.isEmpty()) {
179          maxSpecific = maxSpecific.add(decl);
180        } else {
181          ConstructorDecl other = (ConstructorDecl) maxSpecific.iterator().next();
182          if (decl.moreSpecificThan(other)) {
183            maxSpecific = SimpleSet.emptySet.add(decl);
184          } else if (!other.moreSpecificThan(decl)) {
185            maxSpecific = maxSpecific.add(decl);
186          }
187        }
188        return maxSpecific;
189      }
190    
191      private static SimpleSet MethodAccess.mostSpecific(SimpleSet maxSpecific, MethodDecl decl) {
192        if (maxSpecific.isEmpty()) {
193          maxSpecific = maxSpecific.add(decl);
194        } else {
195          MethodDecl other = (MethodDecl) maxSpecific.iterator().next();
196          if (decl.moreSpecificThan(other)) {
197            maxSpecific = decl;
198          } else if (!other.moreSpecificThan(decl)) {
199            maxSpecific = maxSpecific.add(decl);
200          }
201        }
202        return maxSpecific;
203      }
204    
205      eq ParMethodDecl.lessSpecificThan(MethodDecl m) =
206          genericMethodDecl().lessSpecificThan(m instanceof ParMethodDecl
207              ? ((ParMethodDecl) m).genericMethodDecl() : m );
208    
209      refine MethodDecl eq MethodDecl.lessSpecificThan(MethodDecl m) {
210        int numA = getNumParameter();
211        int numB = m.getNumParameter();
212        int num = Math.max(numA, numB);
213        for (int i = 0; i < num; i++) {
214          TypeDecl t1 = getParameter(Math.min(i, numA-1)).type();
215          TypeDecl t2 = m.getParameter(Math.min(i, numB-1)).type();
216          if (!t1.instanceOf(t2) && !t1.withinBounds(t2, Parameterization.RAW)) {
217            return true;
218          }
219        }
220        return false;
221      }
222    
223      refine ConstructorDecl eq ConstructorDecl.lessSpecificThan(ConstructorDecl m) {
224        int numA = getNumParameter();
225        int numB = m.getNumParameter();
226        int num = Math.max(numA, numB);
227        for (int i = 0; i < num; i++) {
228          TypeDecl t1 = getParameter(Math.min(i, numA-1)).type();
229          TypeDecl t2 = m.getParameter(Math.min(i, numB-1)).type();
230          if (!t1.instanceOf(t2) && !t1.withinBounds(t2, Parameterization.RAW)) {
231            return true;
232          }
233        }
234        return false;
235      }
236    
237      /**
238       * A raw type parameterization. Performs no substitutions.
239       */
240      public static final Parameterization Parameterization.RAW = new Parameterization() {
241        @Override
242        public boolean isRawType() {
243          return true;
244        }
245        @Override
246        public TypeDecl substitute(TypeVariable typeVariable) {
247          return typeVariable;
248        }
249      };
250    
251      /**
252       * A simple parameterization. Each type variable is mapped to a type decl.
253       */
254      class SimpleParameterization implements Parameterization {
255        Map<TypeVariable, TypeDecl> typeMap = new HashMap<TypeVariable, TypeDecl>();
256        public SimpleParameterization(Iterable<TypeVariable> typeParams, Iterable<TypeDecl> typeArgs) {
257          Iterator<TypeVariable> param = typeParams.iterator();
258          Iterator<TypeDecl> arg = typeArgs.iterator();
259          while (param.hasNext() && arg.hasNext()) {
260            typeMap.put(param.next(), arg.next());
261          }
262        }
263    
264        @Override
265        public boolean isRawType() {
266          return false;
267        }
268    
269        @Override
270        public TypeDecl substitute(TypeVariable typeVariable) {
271          if (typeMap.containsKey(typeVariable)) {
272            return typeMap.get(typeVariable);
273          }
274          return typeVariable;
275        }
276      }
277    
278    
279      syn boolean MethodAccess.applicableBySubtyping(MethodDecl m) {
280        if (m.getNumParameter() != getNumArg()) {
281          return false;
282        }
283        for (int i = 0; i < m.getNumParameter(); i++) {
284          TypeDecl arg = getArg(i).type();
285          TypeDecl param = m.getParameter(i).type();
286          if (!param.isTypeVariable()) {
287            if (!arg.instanceOf(param)) {
288              return false;
289            }
290          } else {
291            if (!arg.withinBounds(param, Parameterization.RAW)) {
292              return false;
293            }
294          }
295        }
296        return true;
297      }
298    
299      syn boolean ConstructorDecl.applicableBySubtyping(List<Expr> argList) {
300        if (getNumParameter() != argList.getNumChild()) {
301          return false;
302        }
303        for (int i = 0; i < getNumParameter(); i++) {
304          TypeDecl arg = argList.getChild(i).type();
305          TypeDecl param = getParameter(i).type();
306          if (!param.isTypeVariable()) {
307            if (!arg.instanceOf(param)) {
308              return false;
309            }
310          } else {
311            if (!arg.withinBounds(param, Parameterization.RAW)) {
312              return false;
313            }
314          }
315        }
316        return true;
317      }
318    
319      syn boolean MethodAccess.applicableByMethodInvocationConversion(MethodDecl m) {
320        if (m.getNumParameter() != getNumArg()) {
321          return false;
322        }
323        for (int i = 0; i < m.getNumParameter(); i++)
324          if (!getArg(i).type().methodInvocationConversionTo(m.getParameter(i).type())) {
325            return false;
326          }
327        return true;
328      }
329    
330      syn boolean ConstructorDecl.applicableByMethodInvocationConversion(List<Expr> argList) {
331        if (getNumParameter() != argList.getNumChild()) {
332          return false;
333        }
334        for (int i = 0; i < getNumParameter(); i++) {
335          TypeDecl arg = argList.getChild(i).type();
336          if (!arg.methodInvocationConversionTo(getParameter(i).type())) {
337            return false;
338          }
339        }
340        return true;
341      }
342    
343      syn boolean MethodAccess.applicableVariableArity(MethodDecl m) {
344        for (int i = 0; i < m.getNumParameter() - 1; i++)
345          if (!getArg(i).type().methodInvocationConversionTo(m.getParameter(i).type())) {
346            return false;
347          }
348        for (int i = m.getNumParameter() - 1; i < getNumArg(); i++)
349          if (!getArg(i).type().methodInvocationConversionTo(m.lastParameter().type().componentType())) {
350            return false;
351          }
352        return true;
353      }
354    
355      syn boolean ConstructorDecl.applicableVariableArity(List argList) {
356        for (int i = 0; i < getNumParameter() - 1; i++) {
357          TypeDecl arg = ((Expr) argList.getChild(i)).type();
358          if (!arg.methodInvocationConversionTo(getParameter(i).type())) {
359            return false;
360          }
361        }
362        for (int i = getNumParameter() - 1; i < argList.getNumChild(); i++) {
363          TypeDecl arg = ((Expr) argList.getChild(i)).type();
364          if (!arg.methodInvocationConversionTo(lastParameter().type().componentType())) {
365            return false;
366          }
367        }
368        return true;
369      }
370    
371      /**
372       * @return {@code true} if this is a generic method or constructor, or a
373       * substitued generic method or constructor.
374       */
375      syn boolean BodyDecl.isGeneric() = false;
376      eq GenericMethodDecl.isGeneric() = true;
377      eq MethodDeclSubstituted.isGeneric() = sourceMethodDecl().isGeneric();
378      eq GenericConstructorDecl.isGeneric() = true;
379      eq ConstructorDeclSubstituted.isGeneric() = sourceConstructorDecl().isGeneric();
380    
381      /**
382       * Note: isGeneric must be called first to check if this declaration is generic.
383       * Otherwise this attribute will throw an error!
384       * @return the original generic declaration of this method.
385       */
386      syn GenericMethodDecl MethodDecl.genericDecl() {
387        throw new Error("can not evaulate generic declaration of non-generic method");
388      }
389      eq GenericMethodDecl.genericDecl() = this;
390      eq MethodDeclSubstituted.genericDecl() = sourceMethodDecl().genericDecl();
391    
392      /**
393       * Note: isGeneric must be called first to check if this declaration is generic.
394       * Otherwise this attribute will throw an error!
395       * @return original generic declaration of this constructor.
396       */
397      syn GenericConstructorDecl ConstructorDecl.genericDecl() {
398        throw new Error("can not evaulate generic declaration of non-generic constructor");
399      }
400      eq GenericConstructorDecl.genericDecl() = this;
401      eq ConstructorDeclSubstituted.genericDecl() = sourceConstructorDecl().genericDecl();
402    
403      /**
404       * Note: isGeneric must be called first to check if this declaration is generic.
405       * Otherwise this attribute will throw an error!
406       * @return type parameters for this declaration.
407       */
408      syn List<TypeVariable> BodyDecl.typeParameters() {
409        throw new Error("can not evaulate type parameters for non-generic declaration");
410      }
411    
412      eq GenericMethodDecl.typeParameters() = getTypeParameterList();
413      eq MethodDeclSubstituted.typeParameters() = sourceMethodDecl().typeParameters();
414      eq GenericConstructorDecl.typeParameters() = getTypeParameterList();
415      eq ConstructorDeclSubstituted.typeParameters() = sourceConstructorDecl().typeParameters();
416    
417      // 15.12.2.1
418    
419      /**
420       * A member method is potentially applicable to a method invocation if and
421       * only if all of the following are true:
422       * <ul>
423       *   <li>The name of the member is identical to the name of the method in the
424       *   method invocation.
425       *   <li>The member is accessible (�6.6) to the class or interface in which
426       *   the method invocation appears.
427       *   <li>The arity of the member is lesser or equal to the arity of the
428       *   method invocation.
429       *   <li>If the member is a variable arity method with arity n, the arity of
430       *   the method invocation is greater or equal to n-1.
431       *   <li>If the member is a fixed arity method with arity n, the arity of the
432       *   method invocation is equal to n.
433       *   <li>If the method invocation includes explicit type parameters, and the
434       *   member is a generic method, then the number of actual type parameters is
435       *   equal to the number of formal type parameters.
436       * </ul>
437       */
438      syn boolean MethodAccess.potentiallyApplicable(MethodDecl m) {
439        if (!m.name().equals(name())) {
440          return false;
441        }
442        if (!m.accessibleFrom(hostType())) {
443          return false;
444        }
445        if (m.isVariableArity() && !(arity() >= m.arity()-1)) {
446          return false;
447        }
448        if (!m.isVariableArity() && !(m.arity() == arity())) {
449          return false;
450        }
451        if (m.isGeneric()) {
452          GenericMethodDecl gm = m.genericDecl();
453          ArrayList<TypeDecl> typeArguments = inferTypeArguments(
454              gm.type(),
455              gm.getParameterList(),
456              getArgList(),
457              gm.getTypeParameterList());
458          if (!typeArguments.isEmpty()) {
459            if (gm.getNumTypeParameter() != typeArguments.size()) {
460              return false;
461            }
462            Parameterization par = new SimpleParameterization(gm.getTypeParameterList(), typeArguments);
463            for (int i = 0; i < gm.getNumTypeParameter(); i++) {
464              if (!typeArguments.get(i).withinBounds(gm.original().getTypeParameter(i), par)) {
465                return false;
466              }
467            }
468          }
469        }
470        return true;
471      }
472    
473      syn int MethodDecl.arity() = getNumParameter();
474      syn int MethodAccess.arity() = getNumArg();
475    
476      /**
477       * Infers type arguments for this method invocation.
478       */
479      syn lazy ArrayList<TypeDecl> Expr.inferTypeArguments(
480          TypeDecl resultType,
481          List<ParameterDeclaration> params,
482          List<Expr> args,
483          List<TypeVariable> typeParams) {
484        ArrayList<TypeDecl> typeArguments = new ArrayList<TypeDecl>();
485        Collection<TypeDecl> arguments = computeConstraints(
486            resultType,
487            params,
488            args,
489            typeParams);
490        if (arguments.isEmpty()) {
491          return typeArguments;
492        }
493        int i = 0;
494        for (Iterator<TypeDecl> iter = arguments.iterator(); iter.hasNext(); i++) {
495          TypeDecl typeDecl = iter.next();
496          if (typeDecl == null) {
497            TypeVariable v = typeParams.getChild(i);
498            if (v.getNumTypeBound() == 0) {
499              typeDecl = typeObject();
500            } else if (v.getNumTypeBound() == 1) {
501              typeDecl = v.getTypeBound(0).type();
502            } else {
503              typeDecl = v.lubType();
504            }
505          }
506          typeArguments.add(typeDecl);
507        }
508        return typeArguments;
509      }
510    
511      eq ParMethodAccess.inferTypeArguments(
512          TypeDecl resultType,
513          List<ParameterDeclaration> params,
514          List<Expr> args,
515          List<TypeVariable> typeParams) {
516        ArrayList<TypeDecl> typeArguments = new ArrayList<TypeDecl>();
517        for (Access typeArgument : getTypeArgumentList()) {
518          typeArguments.add(typeArgument.type());
519        }
520        return typeArguments;
521      }
522    
523      eq ParConstructorAccess.inferTypeArguments(
524          TypeDecl resultType,
525          List<ParameterDeclaration> params,
526          List<Expr> args,
527          List<TypeVariable> typeParams) {
528        ArrayList<TypeDecl> typeArguments = new ArrayList<TypeDecl>();
529        for (Access typeArgument : getTypeArgumentList()) {
530          typeArguments.add(typeArgument.type());
531        }
532        return typeArguments;
533      }
534    
535      syn boolean ConstructorDecl.potentiallyApplicable(List<Expr> argList) {
536        if (isVariableArity() && !(argList.getNumChild() >= arity()-1)) {
537          return false;
538        }
539        if (!isVariableArity() && !(arity() == argList.getNumChild())) {
540          return false;
541        }
542        return true;
543      }
544    
545      syn int ConstructorDecl.arity() = getNumParameter();
546      syn int ConstructorAccess.arity() = getNumArg();
547      syn int ClassInstanceExpr.arity() = getNumArg();
548    
549      // 15.12.3
550      // refine old type checking to be valid when using variable arity parameters
551      refine TypeCheck public void MethodAccess.typeCheck() {
552        for (int i = 0; i < getNumArg(); ++i) {
553          if (getArg(i).type().isVoid()) {
554            errorf("expression '%s' has type void and is not a valid method argument",
555                getArg(i).prettyPrint());
556          }
557        }
558        if (isQualified() && decl().isAbstract() && qualifier().isSuperAccess()) {
559          error("may not access abstract methods in superclass");
560        }
561        if (!decl().isVariableArity() || invokesVariableArityAsArray()) {
562          for (int i = 0; i < decl().getNumParameter(); i++) {
563            TypeDecl exprType = getArg(i).type();
564            TypeDecl parmType = decl().getParameter(i).type();
565            if (!exprType.methodInvocationConversionTo(parmType) &&
566                !exprType.isUnknown() && !parmType.isUnknown()) {
567              errorf("argument '%s' of type %s is not compatible with the method parameter type %s",
568                  getArg(i).prettyPrint(), exprType.typeName(), parmType.typeName());
569            }
570          }
571        }
572      }
573    
574      refine MethodDecl eq MethodDecl.signature() {
575        StringBuilder sb = new StringBuilder();
576        sb.append(name() + "(");
577        for (int i = 0; i < getNumParameter(); i++) {
578          if (i != 0) {
579            sb.append(", ");
580          }
581          sb.append(getParameter(i).type().erasure().typeName());
582        }
583        sb.append(")");
584        return sb.toString();
585      }
586    
587      refine MemberMethods eq ClassDecl.methodsSignatureMap() {
588        Map<String,SimpleSet> localMap = localMethodsSignatureMap();
589        Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(localMap);
590        if (hasSuperclass()) {
591          for (Iterator iter = superclass().methodsIterator(); iter.hasNext(); ) {
592            MethodDecl m = (MethodDecl) iter.next();
593            if (!m.isPrivate() && m.accessibleFrom(this) && !localMap.containsKey(m.signature())) {
594              if (!(m instanceof MethodDeclSubstituted)
595                  || !localMap.containsKey(m.sourceMethodDecl().signature())) {
596                putSimpleSetElement(map, m.signature(), m);
597              }
598            }
599          }
600        }
601        for (Iterator iter = interfacesMethodsIterator(); iter.hasNext(); ) {
602          MethodDecl m = (MethodDecl) iter.next();
603          if (m.accessibleFrom(this) && !localMap.containsKey(m.signature())) {
604            if (!(m instanceof MethodDeclSubstituted)
605                || !localMap.containsKey(m.sourceMethodDecl().signature())) {
606              if (allMethodsAbstract((SimpleSet) map.get(m.signature())) &&
607                (!(m instanceof MethodDeclSubstituted) ||
608                 allMethodsAbstract((SimpleSet) map.get(m.sourceMethodDecl().signature()))              )
609              ) {
610                putSimpleSetElement(map, m.signature(), m);
611              }
612            }
613          }
614        }
615        return map;
616      }
617    
618      refine MemberMethods eq InterfaceDecl.methodsSignatureMap() {
619        Map<String,SimpleSet> localMap = localMethodsSignatureMap();
620        Map<String,SimpleSet> map = new HashMap<String,SimpleSet>(localMap);
621        for (Iterator iter = interfacesMethodsIterator(); iter.hasNext(); ) {
622          MethodDecl m = (MethodDecl) iter.next();
623          if (m.accessibleFrom(this) && !localMap.containsKey(m.signature())) {
624            if (!(m instanceof MethodDeclSubstituted) || !localMap.containsKey(m.sourceMethodDecl().signature())) {
625              putSimpleSetElement(map, m.signature(), m);
626            }
627          }
628        }
629        for (Iterator iter = typeObject().methodsIterator(); iter.hasNext(); ) {
630          MethodDecl m = (MethodDecl) iter.next();
631          if (m.isPublic() && !map.containsKey(m.signature())) {
632            putSimpleSetElement(map, m.signature(), m);
633          }
634        }
635        return map;
636      }
637    
638      eq ParTypeDecl.unimplementedMethods() {
639        HashSet set = new HashSet();
640        HashSet result = new HashSet();
641        for (Iterator iter = genericDecl().unimplementedMethods().iterator(); iter.hasNext(); ) {
642          MethodDecl m = (MethodDecl) iter.next();
643          set.add(m.sourceMethodDecl());
644        }
645        for (Iterator iter = super.unimplementedMethods().iterator(); iter.hasNext(); ) {
646          MethodDecl m = (MethodDecl) iter.next();
647          if (set.contains(m.sourceMethodDecl())) {
648            result.add(m);
649          }
650        }
651        return result;
652      }
653    
654    }