001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 aspect VariableArityParameters { 011 // 8.4.1 012 013 /* The last formal parameter in a list is special; it may be a variable arity 014 parameter, indicated by an elipsis following the type.*/ 015 public void VariableArityParameterDeclaration.nameCheck() { 016 super.nameCheck(); 017 if(!variableArityValid()) 018 error("only the last formal paramater may be of variable arity"); 019 } 020 021 eq ConstructorDecl.getParameter(int i).variableArityValid() = i == getNumParameter() - 1; 022 eq MethodDecl.getParameter(int i).variableArityValid() = i == getNumParameter() - 1; 023 eq BasicCatch.getParameter().variableArityValid() = false; 024 eq Program.getChild().variableArityValid() = false; 025 026 inh boolean VariableArityParameterDeclaration.variableArityValid(); 027 028 /* If the last formal parameter is a variable arity parameter of type T, it is 029 considered to define a formal parameter of type T[].*/ 030 eq VariableArityParameterDeclaration.type() = super.type().arrayType(); 031 032 /* The method is then a variable arity method. Otherwise, it is a fixed arity method.*/ 033 syn boolean MethodDecl.isVariableArity() = getNumParameter() == 0 ? false : getParameter(getNumParameter()-1).isVariableArity(); 034 syn boolean ConstructorDecl.isVariableArity() = getNumParameter() == 0 ? false : getParameter(getNumParameter()-1).isVariableArity(); 035 syn boolean ParameterDeclaration.isVariableArity() = false; 036 eq VariableArityParameterDeclaration.isVariableArity() = true; 037 038 syn ParameterDeclaration MethodDecl.lastParameter() = 039 getParameter(getNumParameter() - 1); 040 syn boolean MethodAccess.invokesVariableArityAsArray() { 041 if(!decl().isVariableArity()) 042 return false; 043 if(arity() != decl().arity()) 044 return false; 045 return getArg(getNumArg()-1).type().methodInvocationConversionTo(decl().lastParameter().type()); 046 } 047 syn boolean ConstructorAccess.invokesVariableArityAsArray() { 048 if(!decl().isVariableArity()) 049 return false; 050 if(arity() != decl().arity()) 051 return false; 052 return getArg(getNumArg()-1).type().methodInvocationConversionTo(decl().lastParameter().type()); 053 } 054 syn boolean ClassInstanceExpr.invokesVariableArityAsArray() { 055 if(!decl().isVariableArity()) 056 return false; 057 if(arity() != decl().arity()) 058 return false; 059 return getArg(getNumArg()-1).type().methodInvocationConversionTo(decl().lastParameter().type()); 060 } 061 062 063 syn ParameterDeclaration ConstructorDecl.lastParameter() = 064 getParameter(getNumParameter() - 1); 065 066 // 15.12.2 067 068 /* 069 A method is applicable if it is either applicable by subtyping (�15.12.2.2), 070 applicable by method invocation conversion (�15.12.2.3), or it is an applicable 071 variable arity method (�15.12.2.4). 072 073 The process of determining applicability begins by determining the potentially 074 applicable methods (�15.12.2.1). The remainder of the process is split into 075 three phases. 076 077 The first phase (�15.12.2.2) performs overload resolution without permitting 078 boxing or unboxing conversion, or the use of variable arity method invocation. 079 If no applicable method is found during this phase then processing continues to 080 the second phase. 081 082 The second phase (�15.12.2.3) performs overload resolution while allowing 083 boxing and unboxing, but still precludes the use of variable arity method 084 invocation. If no applicable method is found during this phase then processing 085 continues to the third phase. 086 087 The third phase (�15.12.2.4) allows overloading to be combined with variable 088 arity methods, boxing and unboxing. 089 090 Deciding whether a method is applicable will, in the case of generic methods 091 (�8.4.4), require that actual type arguments be determined. Actual type 092 arguments may be passed explicitly or implicitly. If they are passed 093 implicitly, they must be inferred (�15.12.2.7) from the types of the argument 094 expressions. 095 096 If several applicable methods have been identified during one of the three 097 phases of applicability testing, then the most specific one is chosen, as 098 specified in section �15.12.2.5. See the following subsections for details. 099 */ 100 101 public void VariableArityParameterDeclaration.toString(StringBuffer s) { 102 getModifiers().toString(s); 103 getTypeAccess().toString(s); 104 s.append(" ... " + name()); 105 } 106 107 refine AnonymousClasses 108 protected List AnonymousDecl.constructorParameterList(ConstructorDecl decl) { 109 List parameterList = new List(); 110 for(int i = 0; i < decl.getNumParameter(); i++) { 111 ParameterDeclaration param = decl.getParameter(i); 112 if (param instanceof VariableArityParameterDeclaration) { 113 parameterList.add( 114 new VariableArityParameterDeclaration( 115 new Modifiers(new List()), 116 ((ArrayDecl) param.type()).componentType().createBoundAccess(), 117 param.name() 118 )); 119 } else { 120 parameterList.add( 121 new ParameterDeclaration( 122 param.type().createBoundAccess(), 123 param.name() 124 )); 125 } 126 } 127 128 return parameterList; 129 } 130 131 }