001 /* Copyright (c) 2011, Jesper Öqvist <jesper.oqvist@cs.lth.se> 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 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 032 aspect SafeVarargs { 033 034 /** 035 * @return true if the modifier list includes the SafeVarargs annotation 036 */ 037 syn boolean TypeDecl.hasAnnotationSafeVarargs() = getModifiers().hasAnnotationSafeVarargs(); 038 039 /** 040 * @return true if the modifier list includes the SafeVarargs annotation 041 */ 042 syn boolean BodyDecl.hasAnnotationSafeVarargs() = false; 043 044 /** 045 * @see AST.Modifiers#hasAnnotationSafeVarargs() Modifiers.hasAnnotationSafeVarargs() 046 */ 047 eq MemberTypeDecl.hasAnnotationSafeVarargs() = typeDecl().hasAnnotationSafeVarargs(); 048 049 /** 050 * @see AST.Modifiers#hasAnnotationSafeVarargs() Modifiers.hasAnnotationSafeVarargs() 051 */ 052 eq MethodDecl.hasAnnotationSafeVarargs() = getModifiers().hasAnnotationSafeVarargs(); 053 054 /** 055 * @see AST.Modifiers#hasAnnotationSafeVarargs() Modifiers.hasAnnotationSafeVarargs() 056 */ 057 eq ConstructorDecl.hasAnnotationSafeVarargs() = getModifiers().hasAnnotationSafeVarargs(); 058 059 /** 060 * @see AST.Modifiers#hasAnnotationSafeVarargs() Modifiers.hasAnnotationSafeVarargs() 061 */ 062 eq FieldDeclaration.hasAnnotationSafeVarargs() = getModifiers().hasAnnotationSafeVarargs(); 063 064 /** 065 * @return true if the modifier list includes the SafeVarargs annotation 066 */ 067 syn boolean Modifiers.hasAnnotationSafeVarargs() = hasAnnotation("java.lang", "SafeVarargs"); 068 069 /** 070 * It is an error if the SafeVarargs annotation is used on something 071 * that is not a variable arity method or constructor. 072 */ 073 syn boolean BodyDecl.hasIllegalAnnotationSafeVarargs() = hasAnnotationSafeVarargs(); 074 075 /** 076 * The SafeVarargs annotation is allowed on a constructor if it 077 * has variable arity. 078 */ 079 eq ConstructorDecl.hasIllegalAnnotationSafeVarargs() = hasAnnotationSafeVarargs() && !isVariableArity(); 080 081 /** 082 * The SafeVarargs annotation is allowed on a method if it 083 * has variable arity and is either static or final. 084 */ 085 eq MethodDecl.hasIllegalAnnotationSafeVarargs() = 086 hasAnnotationSafeVarargs() && (!isVariableArity() || (!isFinal() && !isStatic())); 087 088 public void MethodAccess.checkWarnings() { 089 090 MethodDecl decl = decl(); 091 if (decl.getNumParameter() == 0 || decl.getNumParameter() > getNumArg()) { 092 return; 093 } 094 095 ParameterDeclaration param = decl.getParameter(decl.getNumParameter()-1); 096 if (!withinSuppressWarnings("unchecked") 097 && !decl.hasAnnotationSafeVarargs() 098 && param.isVariableArity() 099 && !param.type().isReifiable()) { 100 warning("unchecked array creation for variable " + "arity parameter of " + decl().name()); 101 } 102 } 103 104 /** 105 * We must report illegal uses of the SafeVarargs annotation. 106 * It is only allowed on variable arity method and constructor declarations. 107 */ 108 public void BodyDecl.checkWarnings() { 109 if (hasIllegalAnnotationSafeVarargs()) { 110 error("@SafeVarargs is only allowed for variable arity method and constructor declarations"); 111 } 112 } 113 114 /** 115 * Check if the method is missing a SafeVarargs annotation. 116 */ 117 public void MethodDecl.checkWarnings() { 118 // Check for illegal use of @SafeVarargs. 119 super.checkWarnings(); 120 121 if (!suppressWarnings("unchecked") 122 && !hasAnnotationSafeVarargs() 123 && isVariableArity() 124 && !getParameter(getNumParameter()-1).type().isReifiable()) { 125 warning("possible heap pollution for " 126 + "variable arity parameter"); 127 } 128 } 129 130 }