001 /* 002 * JastAddJ is covered by the modified BSD License. You should have received a copy of the 003 * modified BSD license with this compiler. 004 * 005 * Copyright (c) 2011, Jesper Öqvist <jesper.oqvist@cs.lth.se> 006 * All rights reserved. 007 */ 008 009 aspect MultiCatch { 010 011 /** 012 * Inherit the lookupVariable attribute. 013 */ 014 inh SimpleSet CatchParameterDeclaration.lookupVariable(String name); 015 016 CatchParameterDeclaration implements Variable; 017 syn boolean CatchParameterDeclaration.isParameter() = true; 018 019 // 4.5.3 020 syn boolean CatchParameterDeclaration.isClassVariable() = false; 021 syn boolean CatchParameterDeclaration.isInstanceVariable() = false; 022 inh boolean CatchParameterDeclaration.isMethodParameter(); 023 inh boolean CatchParameterDeclaration.isConstructorParameter(); 024 inh boolean CatchParameterDeclaration.isExceptionHandlerParameter(); 025 syn boolean CatchParameterDeclaration.isLocalVariable() = false; 026 027 eq MultiCatch.getParameter().isMethodParameter() = false; 028 eq MultiCatch.getParameter().isConstructorParameter() = false; 029 eq MultiCatch.getParameter().isExceptionHandlerParameter() = true; 030 031 /** 032 * The catch parameter of a multi-catch clause is implicitly final. 033 */ 034 syn boolean CatchParameterDeclaration.isFinal() = true; 035 syn boolean CatchParameterDeclaration.isVolatile() = getModifiers().isVolatile(); 036 syn boolean CatchParameterDeclaration.isBlank() = false; 037 syn boolean CatchParameterDeclaration.isStatic() = false; 038 039 syn String CatchParameterDeclaration.name() = getID(); 040 041 syn boolean CatchParameterDeclaration.hasInit() = false; 042 syn Expr CatchParameterDeclaration.getInit() { 043 throw new UnsupportedOperationException(); 044 } 045 syn Constant CatchParameterDeclaration.constant() { 046 throw new UnsupportedOperationException(); 047 } 048 049 inh TypeDecl CatchParameterDeclaration.hostType(); 050 syn boolean CatchParameterDeclaration.isSynthetic() = getModifiers().isSynthetic(); 051 052 /** 053 * @see "Generics.jrag" 054 */ 055 eq CatchParameterDeclaration.sourceVariableDecl() = this; 056 057 // Name lookup 058 059 // CatchParameterDeclaration is a SimpleSet 060 CatchParameterDeclaration implements SimpleSet; 061 syn int CatchParameterDeclaration.size() = 1; 062 syn boolean CatchParameterDeclaration.isEmpty() = false; 063 public SimpleSet CatchParameterDeclaration.add(Object o) { 064 return new SimpleSetImpl().add(this).add(o); 065 } 066 syn boolean CatchParameterDeclaration.contains(Object o) = this == o; 067 public boolean CatchParameterDeclaration.isSingleton() { return true; } 068 public boolean CatchParameterDeclaration.isSingleton(Object o) { return contains(o); } 069 070 CatchParameterDeclaration implements Iterator; 071 private CatchParameterDeclaration CatchParameterDeclaration.iterElem; 072 public Iterator CatchParameterDeclaration.iterator() { iterElem = this; return this; } 073 public boolean CatchParameterDeclaration.hasNext() { return iterElem != null; } 074 public Object CatchParameterDeclaration.next() { Object o = iterElem; iterElem = null; return o; } 075 public void CatchParameterDeclaration.remove() { throw new UnsupportedOperationException(); } 076 077 /** 078 * Variable lookup in catch parameter scope. 079 */ 080 eq MultiCatch.getParameter().lookupVariable(String name) = 081 parameterDeclaration(name); 082 083 /** 084 * Variable lookup in catch parameter scope. 085 */ 086 eq MultiCatch.parameterDeclaration(String name) = 087 getParameter().name().equals(name) ? getParameter() : SimpleSet.emptySet; 088 089 /** 090 * Syntactic classification 091 */ 092 eq CatchParameterDeclaration.getTypeAccess(int i).nameType() = NameType.TYPE_NAME; 093 094 eq MultiCatch.handles(TypeDecl exceptionType) { 095 CatchParameterDeclaration param = getParameter(); 096 for (int i = 0; i < param.getNumTypeAccess(); ++i) { 097 TypeDecl type = param.getTypeAccess(i).type(); 098 if (!type.isUnknown() && exceptionType.instanceOf(type)) 099 return true; 100 } 101 return false; 102 } 103 104 /** 105 * Type checking. 106 * The types given in a disjunction type may not be 107 * subtypes of each other. 108 */ 109 public void CatchParameterDeclaration.typeCheck() { 110 boolean pass = true; 111 for (int i = 0; i < getNumTypeAccess(); ++i) { 112 for (int j = 0; j < getNumTypeAccess(); ++j) { 113 if (i == j) continue; 114 TypeDecl t1 = getTypeAccess(i).type(); 115 TypeDecl t2 = getTypeAccess(j).type(); 116 if (t2.instanceOf(t1)) { 117 error(t2.fullName() + " is a subclass of " + 118 t1.fullName()); 119 pass = false; 120 } 121 } 122 } 123 } 124 125 /** 126 * Reachability checking for multi-catch. 127 */ 128 eq MultiCatch.getBlock().reachable() { 129 boolean anyReachable = false; 130 CatchParameterDeclaration param = getParameter(); 131 for (int i = 0; i < param.getNumTypeAccess(); ++i) { 132 TypeDecl type = param.getTypeAccess(i).type(); 133 if (!reachableCatchClause(type)) 134 error("The exception type "+type.fullName()+ 135 " can not be caught "+ 136 "by this multi-catch clause"); 137 else 138 anyReachable = true; 139 } 140 return anyReachable; 141 } 142 143 /** 144 * Pretty printing of multi-catch clause. 145 */ 146 public void MultiCatch.toString(StringBuffer sb) { 147 sb.append("catch ("); 148 getParameter().toString(sb); 149 sb.append(") "); 150 getBlock().toString(sb); 151 } 152 153 /** 154 * Pretty printing of catch parameter declaration. 155 */ 156 public void CatchParameterDeclaration.toString(StringBuffer sb) { 157 getModifiers().toString(sb); 158 for (int i = 0; i < getNumTypeAccess(); ++i) { 159 if (i > 0) sb.append(" | "); 160 getTypeAccess(i).toString(sb); 161 } 162 sb.append(" "+getID()); 163 } 164 165 inh LUBType CatchParameterDeclaration.lookupLUBType(Collection bounds); 166 167 /** 168 * A catch parameter declared with a disjunction type has the 169 * effective type lub(t1, t2, ...) 170 * 171 * @see "JLSv3 §15.12.2.7" 172 */ 173 syn TypeDecl CatchParameterDeclaration.type() { 174 ArrayList<TypeDecl> list = new ArrayList<TypeDecl>(); 175 for (int i = 0; i < getNumTypeAccess(); i++) 176 list.add(getTypeAccess(i).type()); 177 return lookupLUBType(list).lub(); 178 } 179 180 inh VariableScope CatchParameterDeclaration.outerScope(); 181 inh BodyDecl CatchParameterDeclaration.enclosingBodyDecl(); 182 183 /** 184 * Duplicate declaration checking for catch parameters. 185 */ 186 public void CatchParameterDeclaration.nameCheck() { 187 SimpleSet decls = outerScope().lookupVariable(name()); 188 for(Iterator iter = decls.iterator(); iter.hasNext(); ) { 189 Variable var = (Variable)iter.next(); 190 if (var instanceof VariableDeclaration) { 191 VariableDeclaration decl = (VariableDeclaration)var; 192 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) 193 error("duplicate declaration of "+ 194 "catch parameter "+name()); 195 } else if (var instanceof ParameterDeclaration) { 196 ParameterDeclaration decl = (ParameterDeclaration)var; 197 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) 198 error("duplicate declaration of "+ 199 "catch parameter "+name()); 200 } else if (var instanceof CatchParameterDeclaration) { 201 CatchParameterDeclaration decl = (CatchParameterDeclaration)var; 202 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) 203 error("duplicate declaration of "+ 204 "catch parameter "+name()); 205 } 206 } 207 208 // 8.4.1 209 if (!lookupVariable(name()).contains(this)) 210 error("duplicate declaration of catch parameter " + 211 name()); 212 } 213 214 refine NameCheck 215 public void ParameterDeclaration.nameCheck() { 216 SimpleSet decls = outerScope().lookupVariable(name()); 217 for(Iterator iter = decls.iterator(); iter.hasNext(); ) { 218 Variable var = (Variable)iter.next(); 219 if(var instanceof VariableDeclaration) { 220 VariableDeclaration decl = (VariableDeclaration)var; 221 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) 222 error("duplicate declaration of parameter " + name()); 223 } else if(var instanceof ParameterDeclaration) { 224 ParameterDeclaration decl = (ParameterDeclaration)var; 225 if(decl.enclosingBodyDecl() == enclosingBodyDecl()) 226 error("duplicate declaration of parameter " + name()); 227 } else if(var instanceof CatchParameterDeclaration) { 228 CatchParameterDeclaration decl = (CatchParameterDeclaration)var; 229 if(decl.enclosingBodyDecl() == enclosingBodyDecl()) 230 error("duplicate declaration of parameter " + name()); 231 } 232 } 233 234 // 8.4.1 235 if(!lookupVariable(name()).contains(this)) { 236 error("duplicate declaration of parameter " + name()); 237 } 238 } 239 240 refine NameCheck 241 public void VariableDeclaration.nameCheck() { 242 SimpleSet decls = outerScope().lookupVariable(name()); 243 for(Iterator iter = decls.iterator(); iter.hasNext(); ) { 244 Variable var = (Variable)iter.next(); 245 if(var instanceof VariableDeclaration) { 246 VariableDeclaration decl = (VariableDeclaration)var; 247 if(decl != this && decl.enclosingBodyDecl() == enclosingBodyDecl()) 248 error("duplicate declaration of local variable " + name()); 249 } 250 // 8.4.1 251 else if(var instanceof ParameterDeclaration) { 252 ParameterDeclaration decl = (ParameterDeclaration)var; 253 if(decl.enclosingBodyDecl() == enclosingBodyDecl()) 254 error("duplicate declaration of local variable " + name()); 255 } else if(var instanceof CatchParameterDeclaration) { 256 CatchParameterDeclaration decl = (CatchParameterDeclaration)var; 257 if(decl.enclosingBodyDecl() == enclosingBodyDecl()) 258 error("duplicate declaration of local variable " + name()); 259 } 260 } 261 if(getParent().getParent() instanceof Block) { 262 Block block = (Block)getParent().getParent(); 263 for(int i = 0; i < block.getNumStmt(); i++) { 264 if(block.getStmt(i) instanceof Variable) { 265 Variable v = (Variable)block.getStmt(i); 266 if(v.name().equals(name()) && v != this) { 267 error("duplicate declaration of local variable " + name()); 268 } 269 } 270 } 271 } 272 } 273 }