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 029 aspect Java8TypeHierarchyCheck { 030 refine GenericsTypeCheck 031 public void TypeDecl.typeCheck() { 032 // 8.4.6.4 & 9.4.1 033 for (Iterator iter1 = localMethodsIterator(); iter1.hasNext(); ) { 034 MethodDecl m = (MethodDecl)iter1.next(); 035 ASTNode target = m.hostType() == this ? (ASTNode)m : (ASTNode)this; 036 037 for (Iterator i2 = ancestorMethods(m.signature()).iterator(); i2.hasNext(); ) { 038 MethodDecl decl = (MethodDecl)i2.next(); 039 if (m.overrides(decl)) { 040 // 8.4.6.1 041 if (!decl.hostType().isInterfaceDecl() && !m.isStatic() && decl.isStatic()) { 042 target.error("an instance method may not override a static method"); 043 } 044 045 // regardless of overriding 046 // 8.4.6.3 047 if (!m.mayOverride(decl)) { 048 // 9.4.3 049 if (m.isDefault() && decl.hostType() == m.type().typeObject() && !decl.isPrivate()) { 050 target.error("default methods may not override methods in Object"); 051 } else { 052 target.errorf("the return type of method %s in %s does not match the return type of" 053 + " method %s in %s and may thus not be overridden", 054 m.fullSignature(), m.hostType().typeName(), decl.fullSignature(), 055 decl.hostType().typeName()); 056 } 057 } 058 059 // regardless of overriding 060 // 8.4.4 061 for (Access e: m.getExceptionList()) { 062 if (e.type().isCheckedException()) { 063 boolean found = false; 064 for (Access declException: decl.getExceptionList()) { 065 if (e.type().instanceOf(declException.type())) { 066 found = true; 067 break; 068 } 069 } 070 if (!found) { 071 target.errorf("%s in %s may not throw more checked exceptions than" 072 + " overridden method %s in %s", 073 m.fullSignature(), m.hostType().typeName(), decl.fullSignature(), 074 decl.hostType().typeName()); 075 } 076 } 077 } 078 079 // 8.4.6.3 080 if (decl.isPublic() && !m.isPublic()) { 081 target.error("overriding access modifier error"); 082 } 083 // 8.4.6.3 084 if (decl.isProtected() && !(m.isPublic() || m.isProtected())) { 085 target.error("overriding access modifier error"); 086 } 087 // 8.4.6.3 088 if ((!decl.isPrivate() && !decl.isProtected() && !decl.isPublic()) && m.isPrivate()) { 089 target.error("overriding access modifier error"); 090 } 091 // regardless of overriding 092 if (decl.isFinal()) { 093 target.errorf("method %s in %s can not override final method %s in %s", 094 m.fullSignature(), hostType().typeName(), decl.fullSignature(), 095 decl.hostType().typeName()); 096 } 097 } 098 if (m.hides(decl)) { 099 // 8.4.6.2 100 if (m.isStatic() && !decl.isStatic()) { 101 target.error("a static method may not hide an instance method"); 102 } 103 // 8.4.6.3 104 if (!m.mayOverride(decl)) { 105 target.error("can not hide a method with a different return type"); 106 } 107 // 8.4.4 108 for (int i = 0; i < m.getNumException(); i++) { 109 Access e = m.getException(i); 110 boolean found = false; 111 for (int j = 0; !found && j < decl.getNumException(); j++) { 112 if (e.type().instanceOf(decl.getException(j).type())) { 113 found = true; 114 } 115 } 116 if (!found) { 117 target.error("may not throw more checked exceptions than hidden method"); 118 } 119 } 120 // 8.4.6.3 121 if (decl.isPublic() && !m.isPublic()) { 122 target.errorf("hiding access modifier: public method %s in %s is hidden by" 123 + " non public method %s in %s", 124 decl.fullSignature(), decl.hostType().typeName(), m.fullSignature(), 125 m.hostType().typeName()); 126 } 127 // 8.4.6.3 128 if (decl.isProtected() && !(m.isPublic() || m.isProtected())) { 129 target.errorf("hiding access modifier: protected method %s in %s is hidden by" 130 + " non (public|protected) method %s in %s", 131 decl.fullSignature(), decl.hostType().typeName(), m.fullSignature(), 132 m.hostType().typeName()); 133 } 134 // 8.4.6.3 135 if ((!decl.isPrivate() && !decl.isProtected() && !decl.isPublic()) && m.isPrivate()) { 136 target.errorf("hiding access modifier: default method %s in %s is hidden by" 137 + " private method %s in %s", 138 decl.fullSignature(), decl.hostType().typeName(), m.fullSignature(), 139 m.hostType().typeName()); 140 } 141 if (decl.isFinal()) { 142 target.errorf("method %s in %s can not hide final method %s in %s", 143 m.fullSignature(), hostType().typeName(), decl.fullSignature(), 144 decl.hostType().typeName()); 145 } 146 } 147 } 148 } 149 150 151 // different parameterizations of the same generic interface may not be implemented 152 ArrayList list = new ArrayList(); 153 list.addAll(implementedInterfaces()); 154 for (int i = 0; i < list.size(); i++) { 155 InterfaceDecl decl = (InterfaceDecl)list.get(i); 156 if (decl instanceof ParInterfaceDecl) { 157 ParInterfaceDecl p = (ParInterfaceDecl)decl; 158 for (Iterator i2 = list.listIterator(i); i2.hasNext(); ) { 159 InterfaceDecl decl2 = (InterfaceDecl)i2.next(); 160 if (decl2 instanceof ParInterfaceDecl) { 161 ParInterfaceDecl q = (ParInterfaceDecl)decl2; 162 if (p != q && p.genericDecl() == q.genericDecl() && !p.sameArgument(q)) { 163 errorf("%s cannot be inherited with different type arguments: %s and %s", 164 p.genericDecl().name(), p.typeName(), q.typeName()); 165 } 166 } 167 } 168 } 169 } 170 } 171 }