001 /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com> 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * * Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * * Redistributions in binary form must reproduce the above copyright 010 * notice, this list of conditions and the following disclaimer in the 011 * documentation and/or other materials provided with the distribution. 012 * * Neither the name of the Lund University nor the names of its 013 * contributors may be used to endorse or promote products derived from 014 * this software without specific prior written permission. 015 * 016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 026 * POSSIBILITY OF SUCH DAMAGE. 027 */ 028 aspect Java8NameCheck { 029 inh BodyDecl InferredParameterDeclaration.enclosingBodyDecl(); 030 inh VariableScope InferredParameterDeclaration.outerScope(); 031 inh VariableScope LambdaParameters.outerScope(); 032 033 //6.3 034 eq LambdaExpr.getLambdaParameters().outerScope() = this; 035 eq LambdaExpr.getLambdaBody().outerScope() = this; 036 037 038 public void InferredParameterDeclaration.nameCheck() { 039 SimpleSet decls = outerScope().lookupVariable(name()); 040 for (Iterator iter = decls.iterator(); iter.hasNext(); ) { 041 Variable var = (Variable) iter.next(); 042 if (var instanceof VariableDeclaration) { 043 VariableDeclaration decl = (VariableDeclaration) var; 044 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 045 errorf("duplicate declaration of parameter %s", name()); 046 } 047 } else if (var instanceof ParameterDeclaration) { 048 ParameterDeclaration decl = (ParameterDeclaration) var; 049 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 050 errorf("duplicate declaration of parameter %s", name()); 051 } 052 } else if (var instanceof InferredParameterDeclaration) { 053 InferredParameterDeclaration decl = (InferredParameterDeclaration) var; 054 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 055 errorf("duplicate declaration of parameter %s", name()); 056 } 057 } else if (var instanceof CatchParameterDeclaration) { 058 CatchParameterDeclaration decl = (CatchParameterDeclaration) var; 059 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 060 errorf("duplicate declaration of parameter %s", name()); 061 } 062 } 063 } 064 065 // 8.4.1 066 if (!lookupVariable(name()).contains(this)) { 067 errorf("duplicate declaration of parameter %s", name()); 068 } 069 } 070 071 refine MultiCatch 072 public void CatchParameterDeclaration.nameCheck() { 073 SimpleSet decls = outerScope().lookupVariable(name()); 074 for (Iterator iter = decls.iterator(); iter.hasNext(); ) { 075 Variable var = (Variable) iter.next(); 076 if (var instanceof VariableDeclaration) { 077 VariableDeclaration decl = (VariableDeclaration) var; 078 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 079 errorf("duplicate declaration of catch parameter %s", name()); 080 } 081 } else if (var instanceof ParameterDeclaration) { 082 ParameterDeclaration decl = (ParameterDeclaration) var; 083 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 084 errorf("duplicate declaration of catch parameter %s", name()); 085 } 086 } else if (var instanceof InferredParameterDeclaration) { 087 InferredParameterDeclaration decl = (InferredParameterDeclaration) var; 088 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 089 errorf("duplicate declaration of catch parameter %s", name()); 090 } 091 } else if (var instanceof CatchParameterDeclaration) { 092 CatchParameterDeclaration decl = (CatchParameterDeclaration) var; 093 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 094 errorf("duplicate declaration of catch parameter %s", name()); 095 } 096 } 097 } 098 099 // 8.4.1 100 if (!lookupVariable(name()).contains(this)) { 101 errorf("duplicate declaration of catch parameter %s", name()); 102 } 103 } 104 105 refine MultiCatch 106 public void ParameterDeclaration.nameCheck() { 107 SimpleSet decls = outerScope().lookupVariable(name()); 108 for (Iterator iter = decls.iterator(); iter.hasNext(); ) { 109 Variable var = (Variable) iter.next(); 110 if (var instanceof VariableDeclaration) { 111 VariableDeclaration decl = (VariableDeclaration) var; 112 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 113 errorf("duplicate declaration of parameter %s", name()); 114 } 115 } else if (var instanceof ParameterDeclaration) { 116 ParameterDeclaration decl = (ParameterDeclaration) var; 117 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 118 errorf("duplicate declaration of parameter %s", name()); 119 } 120 } else if (var instanceof InferredParameterDeclaration) { 121 InferredParameterDeclaration decl = (InferredParameterDeclaration) var; 122 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 123 errorf("duplicate declaration of parameter %s", name()); 124 } 125 } else if (var instanceof CatchParameterDeclaration) { 126 CatchParameterDeclaration decl = (CatchParameterDeclaration) var; 127 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 128 errorf("duplicate declaration of parameter %s", name()); 129 } 130 } 131 } 132 133 // 8.4.1 134 if (!lookupVariable(name()).contains(this)) { 135 errorf("duplicate declaration of parameter %s", name()); 136 } 137 } 138 139 refine MultiCatch 140 public void VariableDeclaration.nameCheck() { 141 SimpleSet decls = outerScope().lookupVariable(name()); 142 for (Iterator iter = decls.iterator(); iter.hasNext(); ) { 143 Variable var = (Variable) iter.next(); 144 if (var instanceof VariableDeclaration) { 145 VariableDeclaration decl = (VariableDeclaration) var; 146 if (decl != this && decl.enclosingBodyDecl() == enclosingBodyDecl()) { 147 errorf("duplicate declaration of local variable %s", name()); 148 } 149 } 150 // 8.4.1 151 else if (var instanceof ParameterDeclaration) { 152 ParameterDeclaration decl = (ParameterDeclaration) var; 153 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 154 errorf("duplicate declaration of local variable %s", name()); 155 } 156 } else if (var instanceof CatchParameterDeclaration) { 157 CatchParameterDeclaration decl = (CatchParameterDeclaration) var; 158 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 159 errorf("duplicate declaration of local variable %s", name()); 160 } 161 } else if (var instanceof InferredParameterDeclaration) { 162 InferredParameterDeclaration decl = (InferredParameterDeclaration) var; 163 if (decl.enclosingBodyDecl() == enclosingBodyDecl()) { 164 errorf("duplicate declaration of local variable %s", name()); 165 } 166 } 167 } 168 if (getParent().getParent() instanceof Block) { 169 Block block = (Block) getParent().getParent(); 170 for (int i = 0; i < block.getNumStmt(); i++) { 171 if (block.getStmt(i) instanceof Variable) { 172 Variable v = (Variable) block.getStmt(i); 173 if (v.name().equals(name()) && v != this) { 174 errorf("duplicate declaration of local variable %s", name()); 175 } 176 } 177 } 178 } 179 } 180 181 refine NameCheck 182 public void VarAccess.nameCheck() { 183 if (decls().isEmpty() && (!isQualified() || !qualifier().type().isUnknown() 184 || qualifier().isPackageAccess())) { 185 errorf("no field named %s is accessible", name()); 186 } 187 if (decls().size() > 1) { 188 StringBuffer sb = new StringBuffer(); 189 sb.append("several fields named " + name()); 190 for (Iterator iter = decls().iterator(); iter.hasNext(); ) { 191 Variable v = (Variable) iter.next(); 192 sb.append("\n " + v.type().typeName() + "." + v.name() + " declared in " 193 + v.hostType().typeName()); 194 } 195 error(sb.toString()); 196 } 197 198 // 8.8.5.1 199 if (inExplicitConstructorInvocation() && !isQualified() && decl().isInstanceVariable() 200 && hostType() == decl().hostType()) { 201 errorf("instance variable %s may not be accessed in an explicit constructor invocation", 202 name()); 203 } 204 205 Variable v = decl(); 206 if (!v.isClassVariable() && !v.isInstanceVariable() && v.hostType() != hostType() 207 && !v.isEffectivelyFinal()) { 208 error("A parameter/variable used but not declared in an inner class must be" 209 + " final or effectively final"); 210 } 211 212 // 8.3.2.3 213 if ((decl().isInstanceVariable() || decl().isClassVariable()) && !isQualified()) { 214 if (hostType() != null && !hostType().declaredBeforeUse(decl(), this)) { 215 if (inSameInitializer() && !simpleAssignment() && inDeclaringClass()) { 216 BodyDecl b = closestBodyDecl(hostType()); 217 errorf("variable %s is used in %s before it is declared", decl().name(), b.prettyPrint()); 218 } 219 } 220 } 221 222 if (!v.isClassVariable() && !v.isInstanceVariable() && enclosingLambda() != null) { 223 if (v instanceof ParameterDeclaration) { 224 ParameterDeclaration decl = (ParameterDeclaration) v; 225 if (decl.enclosingLambda() != enclosingLambda()) { 226 // 15.27.2 227 if (!decl.isEffectivelyFinal()) { 228 errorf("Parameter %s must be effectively final", v.name()); 229 } 230 } 231 } else if (v instanceof InferredParameterDeclaration) { 232 InferredParameterDeclaration decl = (InferredParameterDeclaration) v; 233 if (decl.enclosingLambda() != enclosingLambda()) { 234 // 15.27.2 235 if (!decl.isEffectivelyFinal()) { 236 errorf("Parameter %s must be effectively final", v.name()); 237 } 238 } 239 } else if (v instanceof VariableDeclaration) { 240 VariableDeclaration decl = (VariableDeclaration) v; 241 if (decl.enclosingLambda() != enclosingLambda()) { 242 // 15.27.2 243 if (!decl.isEffectivelyFinal()) { 244 errorf("Variable %s must be effectively final", v.name()); 245 } 246 // 15.27.2 247 if (!enclosingLambda().isDAbefore(decl)) { 248 errorf("Variable %s must be definitely assigned before used in a lambda", v.name()); 249 } 250 } 251 } 252 } 253 254 } 255 256 refine TypeCheck 257 protected void TypeDecl.checkAbstractMethodDecls(MethodDecl m1, MethodDecl m2) { 258 if (!m1.subsignatureTo(m2) && !m2.subsignatureTo(m1)) { 259 TypeDecl host1 = m1.hostType(); 260 TypeDecl host2 = m2.hostType(); 261 String inh1 = ""; 262 String inh2 = ""; 263 if (host1 != this) { 264 inh1 = "inherited "; 265 } 266 if (host2 != this) { 267 inh2 = "inherited "; 268 } 269 270 //8.4.8.3 271 errorf("%smethod %s and %smethod %s are multiply declared with" 272 + " the same erasure but not override-equivalent signatures in %s", 273 inh1, m1.fullSignature(), inh2, m2.fullSignature(), fullName()); 274 } 275 // DON'T FORGET TO CHECK THIS, REALLY OK TO CHECK BOTH WAYS??? 276 if (!m1.returnTypeSubstitutableFor(m2) && !m2.returnTypeSubstitutableFor(m1)) { 277 String inh1 = ""; 278 TypeDecl host1 = m1.hostType(); 279 TypeDecl host2 = m2.hostType(); 280 if (host1 != this || host2 != this) { 281 inh1 = "inherited "; 282 } 283 284 errorf("%smethod %s is multiply declared with incompatible return types in %s", 285 m1.fullSignature(), fullName()); 286 } 287 } 288 289 protected void TypeDecl.checkInterfaceMethodDecls(MethodDecl m1, MethodDecl m2) { 290 if (m1.isAbstract() && m2.isAbstract()) { 291 checkAbstractMethodDecls(m1, m2); 292 return; 293 } else { 294 TypeDecl host1 = m1.hostType(); 295 TypeDecl host2 = m2.hostType(); 296 String inh1 = ""; 297 String inh2 = ""; 298 if (host1 != this) { 299 inh1 = "inherited "; 300 } 301 if (host2 != this) { 302 inh2 = "inherited "; 303 } 304 305 //9.4 306 errorf("%smethod %s and %smethod %s are multiply declared in %s", 307 inh1, m1.fullSignature(), inh2, m2.fullSignature(), fullName()); 308 } 309 } 310 311 refine TypeHierarchyCheck 312 public void ClassDecl.nameCheck() { 313 refined(); 314 for (Iterator<SimpleSet> iter = methodsSignatureMap().values().iterator(); iter.hasNext(); ) { 315 SimpleSet set = iter.next(); 316 if (set.size() > 1) { 317 Iterator i2 = set.iterator(); 318 boolean foundClassAbstract = false; 319 MethodDecl foundNonAbstract = null; 320 while (i2.hasNext()) { 321 MethodDecl m = (MethodDecl) i2.next(); 322 if (!m.isAbstract()) { 323 foundNonAbstract = m; 324 } else { 325 if (m.hostType().isClassDecl() && m.hostType() != this) { 326 foundClassAbstract = true; 327 } 328 } 329 } 330 // 8.4.8.1 331 if (foundNonAbstract != null && !foundClassAbstract) { 332 errorf("Method %s is multiply declared in %s", 333 foundNonAbstract.fullSignature(), typeName()); 334 } 335 } 336 } 337 } 338 339 refine TypeHierarchyCheck 340 public void InterfaceDecl.nameCheck() { 341 super.nameCheck(); 342 343 //9.6.3.8 344 if (hasAnnotationFunctionalInterface() && !isFunctional()) { 345 errorf("%s is not a functional interface", name()); 346 } 347 348 if (isCircular()) { 349 errorf("circular inheritance dependency in %s", typeName()); 350 } else { 351 for (int i = 0; i < getNumSuperInterface(); i++) { 352 TypeDecl typeDecl = getSuperInterface(i).type(); 353 if (typeDecl.isCircular()) { 354 errorf("circular inheritance dependency in %s", typeName()); 355 } 356 } 357 } 358 for (Iterator<SimpleSet> iter = methodsSignatureMap().values().iterator(); iter.hasNext(); ) { 359 SimpleSet set = iter.next(); 360 if (set.size() > 1) { 361 Iterator i2 = set.iterator(); 362 MethodDecl m = (MethodDecl) i2.next(); 363 while (i2.hasNext()) { 364 MethodDecl n = (MethodDecl) i2.next(); 365 checkInterfaceMethodDecls(m, n); 366 } 367 } 368 } 369 } 370 371 refine TypeHierarchyCheck 372 public void SuperAccess.nameCheck() { 373 if (isQualified()) { 374 if (decl().isInterfaceDecl()) { 375 InterfaceDecl decl = (InterfaceDecl) decl(); 376 if (hostType().isClassDecl()) { 377 ClassDecl hostDecl = (ClassDecl) hostType(); 378 InterfaceDecl found = null; 379 for (int i = 0; i < hostDecl.getNumImplements(); i++) { 380 if (hostDecl.getImplements(i).type() == decl) { 381 found = (InterfaceDecl) hostDecl.getImplements(i).type(); 382 break; 383 } 384 } 385 if (found == null) { 386 // 15.12.1 - fourth bullet 387 errorf("Type %s is not a direct superinterface of %s", 388 decl().typeName(), hostType().typeName()); 389 return; 390 } 391 InterfaceDecl foundRedundant = null; 392 for (int i = 0; i < hostDecl.getNumImplements(); i++) { 393 if (hostDecl.getImplements(i).type() != found && hostDecl.getImplements(i).type().strictSubtype(found)) { 394 foundRedundant = (InterfaceDecl) hostDecl.getImplements(i).type(); 395 break; 396 } 397 } 398 if (foundRedundant != null) { 399 // 15.12.1 - fourth bullet 400 errorf("Type %s cannot be used as qualifier, it is extended by implemented interface %s and is redundant", 401 decl().typeName(), foundRedundant.typeName()); 402 return; 403 } 404 if (hasNextAccess() && nextAccess() instanceof MethodAccess) { 405 MethodAccess methodAccess = (MethodAccess) nextAccess(); 406 if (hostDecl.hasOverridingMethodInSuper(methodAccess.decl())) { 407 errorf("Cannot make a super reference to method %s," 408 + " there is a more specific override", 409 methodAccess.decl().fullSignature()); 410 } 411 } 412 } else if (hostType().isInterfaceDecl()) { 413 InterfaceDecl hostDecl = (InterfaceDecl) hostType(); 414 InterfaceDecl found = null; 415 for (int i = 0; i < hostDecl.getNumSuperInterface(); i++) { 416 if (hostDecl.getSuperInterface(i).type() == decl) { 417 found = (InterfaceDecl) hostDecl.getSuperInterface(i).type(); 418 break; 419 } 420 } 421 if (found == null) { 422 // 15.12.1 - fourth bullet 423 errorf("Type %s is not a direct superinterface of %s", 424 decl().typeName(), hostType().typeName()); 425 return; 426 } 427 InterfaceDecl foundRedundant = null; 428 for (int i = 0; i < hostDecl.getNumSuperInterface(); i++) { 429 if (hostDecl.getSuperInterface(i).type() != found && hostDecl.getSuperInterface(i).type().strictSubtype(found)) { 430 foundRedundant = (InterfaceDecl) hostDecl.getSuperInterface(i).type(); 431 break; 432 } 433 } 434 if (foundRedundant != null) { 435 // 15.12.1 - fourth bullet 436 errorf("Type %s cannot be used as qualifier, it is extended by" 437 + " implemented interface %s and is redundant", 438 decl().typeName(), foundRedundant.typeName()); 439 return; 440 } 441 if (hasNextAccess() && nextAccess() instanceof MethodAccess) { 442 MethodAccess methodAccess = (MethodAccess) nextAccess(); 443 if (hostDecl.hasOverridingMethodInSuper(methodAccess.decl())) { 444 errorf("Cannot make a super reference to method %s," 445 + " there is a more specific override", 446 methodAccess.decl().fullSignature()); 447 } 448 } 449 } else { 450 error("Illegal context for super access"); 451 } 452 453 if (nextAccess() instanceof MethodAccess) { 454 if (((MethodAccess) nextAccess()).decl().isStatic()) { 455 error("Cannot reference static interface methods with super"); 456 } 457 } 458 459 if (!hostType().strictSubtype(decl())) { 460 errorf("Type %s is not a superinterface for %s", 461 decl().typeName(), hostType().typeName()); 462 } 463 } else if (!hostType().isInnerTypeOf(decl()) && hostType() != decl()) { 464 error("qualified super must name an enclosing type"); 465 } 466 if (inStaticContext()) { 467 error("*** Qualified super may not occur in static context"); 468 } 469 } 470 // 8.8.5.1 471 // JLSv7 8.8.7.1 472 TypeDecl constructorHostType = enclosingExplicitConstructorHostType(); 473 if (constructorHostType != null && (constructorHostType == decl())) { 474 error("super may not be accessed in an explicit constructor invocation"); 475 } 476 // 8.4.3.2 477 if (inStaticContext()) { 478 error("super may not be accessed in a static context"); 479 } 480 } 481 482 refine NameCheck 483 eq MethodAccess.validArgs() { 484 for (int i = 0; i < getNumArg(); i++) { 485 if (!getArg(i).isPolyExpression() && getArg(i).type().isUnknown()) { 486 return false; 487 } 488 } 489 return true; 490 } 491 492 refine NameCheck 493 eq ConstructorAccess.validArgs() { 494 for (int i = 0; i < getNumArg(); i++) { 495 if (!getArg(i).isPolyExpression() && getArg(i).type().isUnknown()) { 496 return false; 497 } 498 } 499 return true; 500 } 501 502 refine NameCheck 503 eq ClassInstanceExpr.validArgs() { 504 for (int i = 0; i < getNumArg(); i++) { 505 if (!getArg(i).isPolyExpression() && getArg(i).type().isUnknown()) { 506 return false; 507 } 508 } 509 return true; 510 } 511 512 public void MethodReference.nameCheck() { 513 for (int i = 0; i < getNumTypeArgument(); i++) { 514 if (getTypeArgument(i) instanceof AbstractWildcard) { 515 error("Wildcard not allowed in method reference type argument lists"); 516 break; 517 } 518 } 519 } 520 521 public void ExprMethodReference.nameCheck() { 522 super.nameCheck(); 523 if (!getExpr().isSuperAccess()) { 524 if (!getExpr().type().isReferenceType()) { 525 error("Expression in a method reference must have reference type"); 526 } 527 } 528 } 529 530 public void ClassReference.nameCheck() { 531 for (int i = 0; i < getNumTypeArgument(); i++) { 532 if (getTypeArgument(i) instanceof AbstractWildcard) { 533 error("Wildcard not allowed in constructor reference type argument lists"); 534 break; 535 } 536 } 537 } 538 539 public void ArrayReference.nameCheck() { 540 Access typeAccess = getTypeAccess(); 541 while (typeAccess instanceof ArrayTypeAccess) { 542 typeAccess = ((ArrayTypeAccess) typeAccess).getAccess(); 543 } 544 if (typeAccess instanceof ParTypeAccess) { 545 error("Cannot create array of generic type"); 546 } 547 } 548 549 public void DeclaredLambdaParameters.nameCheck() { 550 for (int i = 0; i < getNumParameter(); i++) { 551 if (getParameter(i).name().equals("_")) { 552 // 15.27.1 553 error("Underscore is not a valid identifier for a lambda parameter"); 554 return; 555 } 556 } 557 } 558 559 public void InferredLambdaParameters.nameCheck() { 560 for (int i = 0; i < getNumParameter(); i++) { 561 if (getParameter(i).name().equals("_")) { 562 // 15.27.1 563 error("Underscore is not a valid identifier for a lambda parameter"); 564 return; 565 } 566 } 567 } 568 }