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 * This aspect adds the Project Coin/JSR 334 Strings in Switch language change 033 * to the ExtendJ frontend. 034 * 035 * <p>The following features were modified: 036 * <ul> 037 * <li>type checking of the switch expression</li> 038 * <li>duplicate checking of switch labels</li> 039 * </ul> 040 */ 041 aspect StringsInSwitch { 042 /** 043 * Overrides the type checking of the switch statement's expression. 044 * 045 * <p>In JSR 334 a switch statement may use an expression of type String. 046 */ 047 refine Enums public void SwitchStmt.typeCheck() { 048 TypeDecl type = getExpr().type(); 049 if ((!type.isIntegralType() || type.isLong()) && !type.isEnumDecl() && !type.isString()) { 050 error("Switch expression must be of type char, byte, short, int, enum, or string"); 051 } 052 } 053 054 /* Type checking for case labels need not be changed as it 055 * already tests if the case labels have expressions which are 056 * assignable to the switch expression 057 */ 058 059 syn boolean Case.isDefaultCase() = false; 060 eq DefaultCase.isDefaultCase() = true; 061 062 /** 063 * This attribute overrides the default duplicate checking for 064 * switch case labels. 065 */ 066 refine Enums eq ConstCase.constValue(Case c) { 067 if (isDefaultCase() || c.isDefaultCase()) { 068 return isDefaultCase() && c.isDefaultCase(); 069 } 070 071 Expr myValue = getValue(); 072 Expr otherValue = ((ConstCase) c).getValue(); 073 TypeDecl myType = myValue.type(); 074 TypeDecl otherType = otherValue.type(); 075 if (myType.isString() || otherType.isString()) { 076 if (!myType.isString() || !otherType.isString()) { 077 return false; 078 } 079 if (!myValue.isConstant() || !otherValue.isConstant()) { 080 return false; 081 } 082 return myValue.constant().stringValue().equals(otherValue.constant().stringValue()); 083 } 084 085 return refined(c); 086 } 087 088 /** 089 * Improve the type checking error messages given for case labels. 090 */ 091 refine Enums public void ConstCase.typeCheck() { 092 boolean isEnumConstant = getValue().isEnumConstant(); 093 TypeDecl switchType = switchType(); 094 TypeDecl type = getValue().type(); 095 if (switchType.isEnumDecl() && !isEnumConstant) { 096 error("Unqualified enumeration constant required"); 097 } 098 if (!type.assignConversionTo(switchType, getValue())) { 099 errorf("Case label has incompatible type %s, expected type compatible with %s", 100 switchType.name(), type.name()); 101 } 102 if (!getValue().isConstant() && !getValue().type().isUnknown() && !isEnumConstant) { 103 error("Case label must have constant expression"); 104 } 105 } 106 107 }