001 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 002 // for details. All rights reserved. Use of this source code is governed by a 003 // BSD-style license that can be found in the LICENSE file. 004 005 package com.google.dart.compiler.backend.js; 006 007 import com.google.dart.compiler.backend.js.ast.*; 008 import org.jetbrains.annotations.NotNull; 009 010 /** 011 * Determines if a statement at the end of a block requires a semicolon. 012 * <p/> 013 * For example, the following statements require semicolons:<br> 014 * <ul> 015 * <li>if (cond);</li> 016 * <li>while (cond);</li> 017 * </ul> 018 * <p/> 019 * The following do not require semicolons:<br> 020 * <ul> 021 * <li>return 1</li> 022 * <li>do {} while(true)</li> 023 * </ul> 024 */ 025 public class JsRequiresSemiVisitor extends JsVisitor { 026 private boolean needsSemicolon; 027 028 private JsRequiresSemiVisitor() { 029 } 030 031 public static boolean exec(JsStatement lastStatement) { 032 JsRequiresSemiVisitor visitor = new JsRequiresSemiVisitor(); 033 visitor.accept(lastStatement); 034 return visitor.needsSemicolon; 035 } 036 037 @Override 038 public void visitFor(@NotNull JsFor x) { 039 if (x.getBody() instanceof JsEmpty) { 040 needsSemicolon = true; 041 } 042 } 043 044 @Override 045 public void visitForIn(@NotNull JsForIn x) { 046 if (x.getBody() instanceof JsEmpty) { 047 needsSemicolon = true; 048 } 049 } 050 051 @Override 052 public void visitIf(@NotNull JsIf x) { 053 JsStatement thenStmt = x.getThenStatement(); 054 JsStatement elseStmt = x.getElseStatement(); 055 JsStatement toCheck = thenStmt; 056 if (elseStmt != null) { 057 toCheck = elseStmt; 058 } 059 if (toCheck instanceof JsEmpty) { 060 needsSemicolon = true; 061 } 062 else { 063 // Must recurse to determine last statement (possible if-else chain). 064 accept(toCheck); 065 } 066 } 067 068 @Override 069 public void visitLabel(@NotNull JsLabel x) { 070 if (x.getStatement() instanceof JsEmpty) { 071 needsSemicolon = true; 072 } 073 } 074 075 @Override 076 public void visitWhile(@NotNull JsWhile x) { 077 if (x.getBody() instanceof JsEmpty) { 078 needsSemicolon = true; 079 } 080 } 081 }