@Check public void checkTypeGuardsOrder(XSwitchExpression expression) { if (isIgnored(IssueCodes.UNREACHABLE_CASE)) { return; } ITypeReferenceOwner owner = new StandardTypeReferenceOwner(getServices(), expression); List<LightweightTypeReference> previousTypeReferences = new ArrayList<LightweightTypeReference>(); for (XCasePart casePart : expression.getCases()) { JvmTypeReference typeGuard = casePart.getTypeGuard(); if (typeGuard == null) { continue; } LightweightTypeReference actualType = owner.toLightweightTypeReference(typeGuard); if (actualType == null) { continue; } if (isHandled(actualType, previousTypeReferences)) { addIssue("Unreachable code: The case can never match. It is already handled by a previous condition.", typeGuard, IssueCodes.UNREACHABLE_CASE); continue; } if (casePart.getCase() == null) { previousTypeReferences.add(actualType); } } }
@Check public void checkTypeGuardsOrderWithGenerics(XSwitchExpression expression) { if (isIgnored(IssueCodes.UNREACHABLE_CASE)) { return; } ITypeReferenceOwner owner = new StandardTypeReferenceOwner(getServices(), expression); List<LightweightTypeReference> previousTypeReferences = new ArrayList<LightweightTypeReference>(); for (XCasePart casePart : expression.getCases()) { JvmTypeReference typeGuard = casePart.getTypeGuard(); if (typeGuard == null) { continue; } LightweightTypeReference typeReference = owner.toLightweightTypeReference(typeGuard); LightweightTypeReference actualType = typeReference.getRawTypeReference(); if (actualType == null || typeReference == actualType) { continue; } if (isHandled(actualType, previousTypeReferences)) { addIssue("Unreachable code: The case can never match. It is already handled by a previous condition (with the same type erasure).", typeGuard, IssueCodes.UNREACHABLE_CASE); continue; } if (casePart.getCase() == null) { previousTypeReferences.add(actualType); } } }
public IScope createFeatureCallSerializationScope(EObject context) { if (!(context instanceof XAbstractFeatureCall)) { return IScope.NULLSCOPE; } XAbstractFeatureCall call = (XAbstractFeatureCall) context; JvmIdentifiableElement feature = call.getFeature(); // this and super - logical container aware FeatureScopes if (feature instanceof JvmType) { return getTypeScope(call, (JvmType) feature); } if (feature instanceof JvmConstructor) { return getThisOrSuperScope(call, (JvmConstructor) feature); } if (feature instanceof JvmExecutable) { return getExecutableScope(call, feature); } if (feature instanceof JvmFormalParameter || feature instanceof JvmField || feature instanceof XVariableDeclaration || feature instanceof XSwitchExpression) { return new SingletonScope(EObjectDescription.create(feature.getSimpleName(), feature), IScope.NULLSCOPE); } return IScope.NULLSCOPE; }
protected String declareLocalVariable(XSwitchExpression expr, ITreeAppendable b) { // declare local var for the switch expression String variableName = getSwitchLocalVariableName(expr, b); if (variableName != null) { return variableName; } String name = createSwitchLocalVariableName(expr); JvmTypeReference variableType = getSwitchLocalVariableType(expr); b.newLine().append("final "); serialize(variableType, expr, b); b.append(" "); variableName = declareAndAppendSwitchSyntheticLocalVariable(expr, name, b); b.append(" = "); internalToJavaExpression(expr.getSwitch(), b); b.append(";"); return variableName; }
protected String getSwitchLocalVariableName(XSwitchExpression expr, ITreeAppendable b) { JvmFormalParameter declaredParam = expr.getDeclaredParam(); if (declaredParam != null) { if (b.hasName(declaredParam)) { return b.getName(declaredParam); } return null; } XExpression switchExpression = expr.getSwitch(); if (b.hasName(switchExpression)) { return b.getName(switchExpression); } if (switchExpression instanceof XFeatureCall) { XFeatureCall featureCall = (XFeatureCall) switchExpression; JvmIdentifiableElement feature = featureCall.getFeature(); if (b.hasName(feature)) { return b.getName(feature); } } return null; }
/** * Determine whether the given switch expression should be compiled to a Java switch for Java version 7 or higher. */ protected boolean isCompiledToJava7Switch(XSwitchExpression expr) { // NOTE: This method could be merged with #isCompiledToJavaSwitch(XSwitchExpression) if (!switchExpressions.isJava7SwitchExpression(expr)) { return false; } for (XCasePart casePart : expr.getCases()) { if (!switchExpressions.isJavaCaseExpression(expr, casePart)) { return false; } if (!switchExpressions.isConstant(casePart)) { return false; } } return true; }
protected ILocationData getLocationOfDefault(XSwitchExpression expression) { final ICompositeNode startNode = NodeModelUtils.getNode(expression); if (startNode != null) { List<INode> resultNodes = Lists.newArrayList(); boolean defaultSeen = false; for (INode child : startNode.getChildren()) { if (defaultSeen) { resultNodes.add(child); if (GrammarUtil.containingAssignment(child.getGrammarElement()) != null) { break; } } else if (child.getGrammarElement() instanceof Keyword && "default".equals(child.getText())) { defaultSeen = true; resultNodes.add(child); } } return toLocationData(resultNodes); } return null; }
/** * Determine whether the given switch expression is valid for Java version 6 or lower. */ public boolean isJavaSwitchExpression(final XSwitchExpression it) { boolean _xblockexpression = false; { final LightweightTypeReference switchType = this.getSwitchVariableType(it); if ((switchType == null)) { return false; } boolean _isSubtypeOf = switchType.isSubtypeOf(Integer.TYPE); if (_isSubtypeOf) { return true; } boolean _isSubtypeOf_1 = switchType.isSubtypeOf(Enum.class); if (_isSubtypeOf_1) { return true; } _xblockexpression = false; } return _xblockexpression; }
/** * Determine whether the given switch expression is valid for Java version 7 or higher. */ public boolean isJava7SwitchExpression(final XSwitchExpression it) { boolean _xblockexpression = false; { final LightweightTypeReference switchType = this.getSwitchVariableType(it); if ((switchType == null)) { return false; } boolean _isSubtypeOf = switchType.isSubtypeOf(Integer.TYPE); if (_isSubtypeOf) { return true; } boolean _isSubtypeOf_1 = switchType.isSubtypeOf(Enum.class); if (_isSubtypeOf_1) { return true; } boolean _isSubtypeOf_2 = switchType.isSubtypeOf(String.class); if (_isSubtypeOf_2) { return true; } _xblockexpression = false; } return _xblockexpression; }
public LightweightTypeReference getSwitchVariableType(final XSwitchExpression it) { @Extension final IResolvedTypes resolvedTypes = this._iBatchTypeResolver.resolveTypes(it); final JvmFormalParameter declaredParam = it.getDeclaredParam(); if ((declaredParam == null)) { return resolvedTypes.getActualType(it.getSwitch()); } final LightweightTypeReference paramType = resolvedTypes.getActualType(declaredParam); LightweightTypeReference _elvis = null; if (paramType != null) { _elvis = paramType; } else { LightweightTypeReference _actualType = resolvedTypes.getActualType(it.getSwitch()); _elvis = _actualType; } return _elvis; }
public XExpression getThen(final XCasePart casePart, final XSwitchExpression switchExpression) { final XExpression then = casePart.getThen(); if ((then != null)) { return then; } final int casePartIndex = switchExpression.getCases().indexOf(casePart); if ((casePartIndex == (-1))) { return null; } final int count = switchExpression.getCases().size(); if ((casePartIndex == (count - 1))) { return switchExpression.getDefault(); } if (((casePartIndex + 1) < count)) { return this.getThen(switchExpression.getCases().get((casePartIndex + 1)), switchExpression); } return null; }
@Check public void checkTypeGuards(XCasePart casePart) { if (casePart.getTypeGuard() == null) return; LightweightTypeReference typeGuard = toLightweightTypeReference(casePart.getTypeGuard()); if (typeGuard.isPrimitive()) { error("Primitives are not allowed as type guards", Literals.XCASE_PART__TYPE_GUARD, INVALID_USE_OF_TYPE); return; } LightweightTypeReference targetTypeRef = getActualType(((XSwitchExpression) casePart.eContainer()).getSwitch()); checkCast(casePart.getTypeGuard(), typeGuard, targetTypeRef); }
@Check public void checkLocalUsageOfSwitchParameter(XSwitchExpression switchExpression) { JvmFormalParameter switchParam = switchExpression.getDeclaredParam(); if(!isIgnored(UNUSED_LOCAL_VARIABLE) && switchParam != null && !isLocallyUsed(switchParam, switchExpression)){ String message = "The value of the local variable " + switchParam.getName() + " is not used"; addIssue(message, switchParam, TypesPackage.Literals.JVM_FORMAL_PARAMETER__NAME, UNUSED_LOCAL_VARIABLE); } }
@Check public void checkRedundantCase(XSwitchExpression switchExpression) { XCasePart casePart = IterableExtensions.last(switchExpression.getCases()); if (casePart == null || !(casePart.isFallThrough() && casePart.getThen() == null)) { return; } if (switchExpression.getDefault() == null) { error("Redundant case.", casePart, null, IssueCodes.REDUNDANT_CASE); } else { warning("Redundant case.", casePart, null, IssueCodes.REDUNDANT_CASE); } }
@Check public void checkDeadCode(XSwitchExpression switchExpression) { List<XCasePart> cases = switchExpression.getCases(); for(int i = 0, size = cases.size(); i < size; i++) { XCasePart casePart = cases.get(i); XExpression caseExpression = casePart.getCase(); if (!earlyExitComputer.isEarlyExit(caseExpression)) { validateCondition(caseExpression, false); } else if (!markAsDeadCode(casePart.getThen())) { if (casePart.getTypeGuard() == null) { i = markAsDeadCode(cases, casePart, i, size); } } } }
protected ITypeComputationState getSwitchExpressionState(XSwitchExpression expr, ITypeComputationState state) { JvmFormalParameter param = expr.getDeclaredParam(); if (param == null) { return state.withNonVoidExpectation(); } JvmTypeReference parameterType = param.getParameterType(); if (parameterType == null) { return state.withNonVoidExpectation(); } LightweightTypeReference expectation = state.getReferenceOwner().toLightweightTypeReference(parameterType); return state.withExpectation(expectation); }
@Override protected void internalToConvertedExpression(XExpression obj, ITreeAppendable appendable) { if (obj instanceof XBlockExpression) { _toJavaExpression((XBlockExpression) obj, appendable); } else if (obj instanceof XCastedExpression) { _toJavaExpression((XCastedExpression) obj, appendable); } else if (obj instanceof XClosure) { _toJavaExpression((XClosure) obj, appendable); } else if (obj instanceof XAnnotation) { _toJavaExpression((XAnnotation) obj, appendable); } else if (obj instanceof XConstructorCall) { _toJavaExpression((XConstructorCall) obj, appendable); } else if (obj instanceof XIfExpression) { _toJavaExpression((XIfExpression) obj, appendable); } else if (obj instanceof XInstanceOfExpression) { _toJavaExpression((XInstanceOfExpression) obj, appendable); } else if (obj instanceof XSwitchExpression) { _toJavaExpression((XSwitchExpression) obj, appendable); } else if (obj instanceof XTryCatchFinallyExpression) { _toJavaExpression((XTryCatchFinallyExpression) obj, appendable); } else if (obj instanceof XListLiteral) { _toJavaExpression((XListLiteral) obj, appendable); } else if (obj instanceof XSetLiteral) { _toJavaExpression((XSetLiteral) obj, appendable); } else if (obj instanceof XSynchronizedExpression) { _toJavaExpression((XSynchronizedExpression) obj, appendable); } else if (obj instanceof XReturnExpression) { _toJavaExpression((XReturnExpression) obj, appendable); } else if (obj instanceof XThrowExpression) { _toJavaExpression((XThrowExpression) obj, appendable); } else { super.internalToConvertedExpression(obj, appendable); } }
protected void _toJavaStatement(XSwitchExpression expr, ITreeAppendable b, boolean isReferenced) { GeneratorConfig config = b.getGeneratorConfig(); boolean compileToSwitch; if (config != null && config.getJavaSourceVersion().isAtLeast(JAVA7)) { compileToSwitch = isCompiledToJava7Switch(expr); } else { compileToSwitch = isCompiledToJavaSwitch(expr); } if (compileToSwitch) { _toJavaSwitchStatement(expr, b, isReferenced); } else { _toJavaIfElseStatement(expr, b, isReferenced); } }
protected String createSwitchLocalVariableName(XSwitchExpression expr) { String name = getSwitchLocalVariableSimpleName(expr); if (name != null) { return makeJavaIdentifier(name); } // define synthetic name return "_switchValue"; }
protected String getSwitchLocalVariableSimpleName(XSwitchExpression expr) { IdentifiableSimpleNameProvider nameProvider = getNameProvider(); String varName = nameProvider.getSimpleName(expr.getDeclaredParam()); if (varName != null) { return varName; } XExpression expression = expr.getSwitch(); if (!(expression instanceof XFeatureCall)) { return null; } XFeatureCall featureCall = (XFeatureCall) expression; JvmIdentifiableElement feature = featureCall.getFeature(); return nameProvider.getSimpleName(feature); }
protected JvmTypeReference getSwitchLocalVariableType(XSwitchExpression expr) { JvmFormalParameter declaredParam = expr.getDeclaredParam(); if (declaredParam == null) { return getType(expr.getSwitch()); } return getParameterType(declaredParam); }
protected String declareSwitchResultVariable(XSwitchExpression expr, ITreeAppendable b, boolean isReferenced) { LightweightTypeReference type = getTypeForVariableDeclaration(expr); String switchResultName = b.declareSyntheticVariable(getSwitchExpressionKey(expr), "_switchResult"); if (isReferenced) { b.newLine(); b.append(type); b.append(" ").append(switchResultName).append(" = "); b.append(getDefaultValueLiteral(expr)); b.append(";"); } return switchResultName; }
protected void executeThenPart(XSwitchExpression expr, String switchResultName, XExpression then, ITreeAppendable b, boolean isReferenced) { final boolean canBeReferenced = isReferenced && !isPrimitiveVoid(then); internalToJavaStatement(then, b, canBeReferenced); if (canBeReferenced) { b.newLine().append(switchResultName).append(" = "); internalToConvertedExpression(then, b, getLightweightType(expr)); b.append(";"); } }
/** * Determine whether the given switch expression should be compiled to a Java switch for Java version 6 or lower. */ protected boolean isCompiledToJavaSwitch(XSwitchExpression expr) { if (!switchExpressions.isJavaSwitchExpression(expr)) { return false; } for (XCasePart casePart : expr.getCases()) { if (!switchExpressions.isJavaCaseExpression(expr, casePart)) { return false; } if (!switchExpressions.isConstant(casePart)) { return false; } } return true; }
protected boolean allCasesAreExitedEarly(XSwitchExpression expr) { for(XCasePart casePart: expr.getCases()) { if(casePart.getThen() != null && !isEarlyExit(casePart.getThen())) { return false; } } return true; }
@Override /* @Nullable */ protected String getReferenceName(XExpression expr, ITreeAppendable b) { if (expr instanceof XSwitchExpression) { Object key = getSwitchExpressionKey((XSwitchExpression) expr); if (b.hasName(key)) return b.getName(key); } return super.getReferenceName(expr, b); }
protected void _toJavaExpression(XSwitchExpression expr, ITreeAppendable b) { final String referenceName = getReferenceName(expr, b); if (referenceName != null) b.trace(expr, false).append(referenceName); else throw new IllegalStateException("Switch expression wasn't translated to Java statements before."); }
protected void _findImplicitReturns(final XSwitchExpression expression, final ImplicitReturnFinder.Acceptor acceptor) { final Consumer<XCasePart> _function = (XCasePart it) -> { this.findImplicitReturns(it.getThen(), acceptor); }; expression.getCases().forEach(_function); this.findImplicitReturns(expression.getDefault(), acceptor); }
protected Collection<IEarlyExitComputer.ExitPoint> exitPoints(final XExpression expression) { if (expression instanceof XDoWhileExpression) { return _exitPoints((XDoWhileExpression)expression); } else if (expression instanceof XWhileExpression) { return _exitPoints((XWhileExpression)expression); } else if (expression instanceof XAbstractFeatureCall) { return _exitPoints((XAbstractFeatureCall)expression); } else if (expression instanceof XBasicForLoopExpression) { return _exitPoints((XBasicForLoopExpression)expression); } else if (expression instanceof XBlockExpression) { return _exitPoints((XBlockExpression)expression); } else if (expression instanceof XConstructorCall) { return _exitPoints((XConstructorCall)expression); } else if (expression instanceof XForLoopExpression) { return _exitPoints((XForLoopExpression)expression); } else if (expression instanceof XIfExpression) { return _exitPoints((XIfExpression)expression); } else if (expression instanceof XReturnExpression) { return _exitPoints((XReturnExpression)expression); } else if (expression instanceof XSwitchExpression) { return _exitPoints((XSwitchExpression)expression); } else if (expression instanceof XSynchronizedExpression) { return _exitPoints((XSynchronizedExpression)expression); } else if (expression instanceof XThrowExpression) { return _exitPoints((XThrowExpression)expression); } else if (expression instanceof XTryCatchFinallyExpression) { return _exitPoints((XTryCatchFinallyExpression)expression); } else if (expression instanceof XVariableDeclaration) { return _exitPoints((XVariableDeclaration)expression); } else if (expression != null) { return _exitPoints(expression); } else { throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object>asList(expression).toString()); } }
public boolean isJavaCaseExpression(final XSwitchExpression it, final XCasePart casePart) { boolean _xblockexpression = false; { JvmTypeReference _typeGuard = casePart.getTypeGuard(); boolean _tripleNotEquals = (_typeGuard != null); if (_tripleNotEquals) { return false; } final XExpression case_ = casePart.getCase(); if ((case_ == null)) { return false; } @Extension final IResolvedTypes resolvedTypes = this._iBatchTypeResolver.resolveTypes(it); final LightweightTypeReference caseType = resolvedTypes.getActualType(case_); if ((caseType == null)) { return false; } final LightweightTypeReference switchType = this.getSwitchVariableType(it); boolean _isAssignableFrom = switchType.isAssignableFrom(caseType); boolean _not = (!_isAssignableFrom); if (_not) { return false; } _xblockexpression = true; } return _xblockexpression; }
@Override protected List<XCasePart> getCases(XSwitchExpression switchExpression) { List<XCasePart> result = super.getCases(switchExpression); for(XCasePart casePart: result) { if (casePart.getThen() == null) { return result; } } return Lists.reverse(result); }
@Test public void testSwitch_0() throws Exception { XSwitchExpression se = (XSwitchExpression) expression("switch true { case 1==0 : '1' }"); assertNull(se.getDefault()); assertEquals(1, se.getCases().size()); assertNotNull(se.getSwitch()); XCasePart casePart = se.getCases().get(0); assertTrue(casePart.getCase() instanceof XBinaryOperation); assertTrue(casePart.getThen() instanceof XStringLiteral); }
@Test public void testSwitch_1() throws Exception { XSwitchExpression se = (XSwitchExpression) expression("switch number{case 1:'1' case 2:'2' default:'3'}"); assertTrue(se.getDefault() instanceof XStringLiteral); assertEquals(2, se.getCases().size()); assertTrue(se.getSwitch() instanceof XFeatureCall); XCasePart case1 = se.getCases().get(0); assertEquals("1", ((XNumberLiteral) case1.getCase()).getValue()); assertTrue(case1.getThen() instanceof XStringLiteral); XCasePart case2 = se.getCases().get(1); assertEquals("2", ((XNumberLiteral) case2.getCase()).getValue()); assertTrue(case2.getThen() instanceof XStringLiteral); }
protected void doTestSwitch_2(XSwitchExpression se) { assertEquals(2,se.getCases().size()); assertNull(se.getDefault()); XCasePart c1 = se.getCases().get(0); assertEquals("java.lang.String",c1.getTypeGuard().getIdentifier()); assertFeatureCall("length",c1.getCase()); assertFeatureCall("foo",((XMemberFeatureCall)c1.getCase()).getMemberCallTarget()); assertFeatureCall("bar",c1.getThen()); XCasePart c2 = se.getCases().get(1); assertEquals("java.lang.String",c2.getTypeGuard().getIdentifier()); assertNull(c2.getCase()); assertFeatureCall("baz",((XBlockExpression)c2.getThen()).getExpressions().get(0)); }
@Test public void testSwitchExpression_0() throws Exception { XSwitchExpression exp = (XSwitchExpression) expressionWithExpectedType( "switch null {" + " java.lang.Boolean case null : null" + " default : null" + "}", "String"); assertExpected(null,exp.getSwitch()); for (XCasePart cp : exp.getCases()) { assertExpected(null, cp.getCase()); assertExpected("java.lang.String", cp.getThen()); } assertExpected("java.lang.String", exp.getDefault()); }
@Test public void testSwitchExpression_1() throws Exception { XSwitchExpression exp = (XSwitchExpression) expressionWithExpectedType( "switch true {" + " java.lang.Boolean case null : null" + " default : null" + "}", "String"); for (XCasePart cp : exp.getCases()) { assertExpected(null, cp.getCase()); assertExpected("java.lang.String", cp.getThen()); } assertExpected("java.lang.String", exp.getDefault()); }
@Test public void testTypeGuardedCase_0() throws Exception { XSwitchExpression expression = (XSwitchExpression) expression("switch s: new Object() { String: s StringBuffer: s}", true); // assertEquals("java.lang.Object", toString(typeProvider.getType(expression.getSwitch()))); // assertEquals("java.lang.String", toString(typeProvider.getType(expression.getCases().get(0).getThen()))); // assertEquals("java.lang.StringBuffer", toString(typeProvider.getType(expression.getCases().get(1).getThen()))); assertEquals("java.io.Serializable & java.lang.CharSequence", toString(getType(expression))); }
@Test public void testTypeGuardedCase_1() throws Exception { XSwitchExpression expression = (XSwitchExpression) expression("switch s: '' as CharSequence { Cloneable: s String: s }", true); assertEquals("java.lang.CharSequence", toString(getType(expression.getSwitch()))); assertEquals("java.lang.CharSequence & java.lang.Cloneable", toString(getType(expression.getCases().get(0).getThen()))); assertEquals("java.lang.String", toString(getType(expression.getCases().get(1).getThen()))); assertEquals("java.lang.CharSequence", toString(getType(expression))); }
@Test public void testSwitchExpression_01() throws Exception { XSwitchExpression switchExpr = (XSwitchExpression) expression( "switch x : new Object() { " + " case x : x" + "}"); final XCasePart xCasePart = switchExpr.getCases().get(0); assertEquals(switchExpr.getDeclaredParam(), ((XFeatureCall) xCasePart.getThen()).getFeature()); assertEquals(switchExpr.getDeclaredParam(), ((XFeatureCall) xCasePart.getCase()).getFeature()); }
@Test public void testSwitchExpression_02() throws Exception { XSwitchExpression switchExpr = (XSwitchExpression) expression( "switch x : new Object() { " + " case true : true "+ " default : x" + "}"); assertEquals(switchExpr.getDeclaredParam(), ((XFeatureCall)switchExpr.getDefault()).getFeature()); }